1.创建socketfd和epoll
// 创建epollfd. int epfd = epoll_create(1);
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
2.绑定端口号
struct sockaddr_in serveraddr; serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(17099); // 绑定. if (bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(struct sockaddr)) == -1) { perror("bind"); exit(-1); }
3. 监听
// 监听. if (-1 == listen(sockfd, 10)) { perror("listen"); exit(-1); }
4.将这个fd加入epoll(水平触发)
// 将socketfd添加到epoll. struct epoll_event ep_event; ep_event.events = EPOLLIN; ep_event.data.fd = sockfd; if (epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, &ep_event) == -1) { perror("epoll_ctl"); exit(-1); }
5.声明epoll_event数组,然后循环epoll_wait
struct epoll_event events[1024] = {0}; while (1) { int nready = epoll_wait(epfd, events, 1024, -1);
6.遍历nready,然后判断是否是服务端socket
for (int i = 0; i < nready; i++) { struct sockaddr_in clientaddr; socklen_t len = sizeof(clientaddr); char ip[20]; if (events[i].data.fd == sockfd) {
7.然后accept获取客户端socket,并添加到epoll
int client = accept(events[i].data.fd, (struct sockaddr *)&clientaddr, &len); inet_ntop(AF_INET, &(clientaddr.sin_addr), ip, len); printf("%d connect: ip %s port %d\n", client, ip, clientaddr.sin_port); // 将新的fd添加到epoll ep_event.data.fd = client; epoll_ctl(epfd, EPOLL_CTL_ADD, client, &ep_event);
8.如果epoll_wait有EPOLL_IN事件,则说明有消息,recv
}else if(events[i].events & EPOLLIN){ char buffer[1024] = {0}; int count = recv(events[i].data.fd, &buffer, sizeof(buffer), 0);
9.如果这个count是-1,则说明recv错误;如果是0,则说明客户端断开;如果大于0,则说明有消息
if (count == -1) { printf("recv error %m\n"); continue; } else if (count == 0) { // 说明连接断开. printf("%d disconnect: ip %s port %d\n", events[i].data.fd, ip, clientaddr.sin_port); close(events[i].data.fd); epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL); } else { printf("recv: %s\n", buffer); send(events[i].data.fd, &buffer, count, 0); }
标签:struct,epoll,用法,fd,events,data,event From: https://www.cnblogs.com/anlingxiao/p/18072441