非阻塞,et模型 epoll
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/epoll.h> #include <netinet/in.h> #include <unistd.h> #include <arpa/inet.h> #include <fcntl.h> #include <errno.h> #define MAX_EVENTS 100 #define MAX_BUFFER_SIZE 10 /*设置非阻塞*/ int setNonBlock(int fd) { int old_flag = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, old_flag | O_NONBLOCK); return old_flag; } /*添加到epoll池中*/ void addfd_to_epoll(int epfd, int fd) { struct epoll_event event; event.data.fd = fd; event.events = EPOLLIN | EPOLLET; setNonBlock(fd); epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event); } void err_exit(char *msg) { perror(msg); exit(1); } int create_socket(char *ip, int port) { struct sockaddr_in addr; int sockfd, reuse = 1; memset(&addr, 0, sizeof(sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = htons(port); if(inet_pton(PF_INET, ip, &addr.sin_addr) == -1) { err_exit("inet_pton() error"); } if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1) { err_exit("socket() error"); } if(-1 == setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))) { err_exit("setsockopt() error"); } if(-1 == bind(sockfd, (struct sockaddr*)&addr, sizeof(addr))) { err_exit("bind() error"); } //待处理连接最大5 if(-1 == listen(sockfd, 5)) { err_exit("listen() error"); } return sockfd; } void epoll_process(int epfd, struct epoll_event *events, int num, int listenfd) { struct sockaddr addr; int newfd, confd; socklen_t len; for(int i = 0; i < num; ++i) { newfd = events[i].data.fd; if(newfd == listenfd) { confd = accept(listenfd, &addr, &len); addfd_to_epoll(epfd, confd); } else { printf("开始接受客户端%d数据 \n", newfd); //et的循环接受数据 char szBuf[MAX_BUFFER_SIZE + 1]; while(1) { memset(&szBuf, 0, sizeof(szBuf)); int ret = recv(newfd, szBuf, MAX_BUFFER_SIZE, 0); if(ret == 0) { printf("客户端主动关闭请求\n"); close(newfd); break; } else if(ret == -1) { if(errno == EAGAIN || errno == EWOULDBLOCK) { printf("循环读取完了所有的数据 \n"); break; } else if(104 == errno) //connetction reset by peer { printf("客户端主动关闭请求\n"); } close(newfd); break; } else { printf("接受到数据%d字节,数据: %s\n", ret, szBuf); } } } } } int main(int argc, char** argv) { if(argc < 3) { fprintf(stderr, "usage:%s ip_address port_number\n", argv[0]); exit(0); } int listenfd, epfd; listenfd = create_socket(argv[1], atoi(argv[2])); epfd = epoll_create(100000); if(-1 == epfd) exit(-1); addfd_to_epoll(epfd, listenfd); struct epoll_event events[MAX_EVENTS + 1]; while(1) { int num = epoll_wait(epfd, events, MAX_EVENTS, 0); if(num == -1) { err_exit("epoll_wait() error"); } else { epoll_process(epfd, events, num, listenfd); } usleep(10); } close(listenfd); return 0; }