网站制作的详情表,水陆运输类网站如何建设,中核华兴建设有限公司投标网站,discuz做网站epoll实现TCP特大型并发服务器的流程#xff1a;一、创建套接字#xff08;socket函数#xff09;#xff1a;通信域选择IPV4网络协议、套接字类型选择流式#xff1b; int sock_fd socket(AF_INET,SOCK_STREAM,0); //通信域选择IPV4、套接字类型选择流式二、填充服务器和…epoll实现TCP特大型并发服务器的流程一、创建套接字socket函数通信域选择IPV4网络协议、套接字类型选择流式 int sock_fd socket(AF_INET,SOCK_STREAM,0); //通信域选择IPV4、套接字类型选择流式二、填充服务器和客户机的网络信息结构体1.分别定义服务器网络信息结构体变量serveraddr和客户机网络信息结构体变量clientaddr2.分别求出服务器和客户机的网络信息结构体变量的内存空间大小以作备用3.网络信息结构体清04.使用IPV4网络协议AF_INET5.在终端预留服务器端主机的IP地址inet_addr(argv[1])6.在终端预留服务器端网络字节序的端口号htons(atoi(argv[2])) struct sockaddr_in serveraddr; //定义服务器网络信息结构体变量struct sockaddr_in clientaddr;socklen_t serveraddr_len sizeof(serveraddr);//求出服务器结构体变量的内存空间大小socklen_t clientaddr_len sizeof(clientaddr);//求出客户机结构体变量的内存空间大小memset(serveraddr,0,serveraddr_len); //服务器结构体清零memset(clientaddr,0,clientaddr_len);//客户机结构体清零serveraddr.sin_family AF_INET; //使用IPV4网络协议serveraddr.sin_addr.s_addr inet_addr(argv[1]); //IP地址serveraddr.sin_port htons(atoi(argv[2]));//网络字节序的端口号三、设置允许端口复用setsockopt函数setsockopt函数功能设置套接字属性
#include sys/types.h#include sys/socket.hint setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen); /*参数sockfd套接字level 选项的级别套接字API级别 SOL_SOCKETTCP级别 IPPROTO_TCPIP级别 IPPROTO_IPoptname选项的名字套接字API级别SO_BROADCAST 是否允许发送广播SO_RCVBUF 接收缓冲区的大小SO_SNDBUF 发送缓冲区的大小SO_RCVTIMEO 接收超时时间参数使用的是 struct timeval 结构体如果超时了 函数调用会立即返回-1并将错误码置成 EAGAINSO_SNDTIMEO 发送超时时间SO_REUSEADDR 端口复用TCP级别TCP_NODELAY 使能/禁用Nagle算法IP级别IP_ADD_MEMBERSHIP 设置加入多播组optval 选项的值没有特殊说明时 使用的都是int类型optlenoptval的大小返回值成功 0失败 -1 重置错误码*/特别注意使用setsockopt设置允许端口复用时其在代码的位置在填充网络信息结构体和bind之间 int reuse 1;if(-1 (setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,reuse,sizeof(reuse)))){perror(setsockopt error);exit(-1);}四、套接字和服务器的网络信息结构体进行绑定bind函数 int ret bind(sock_fd,(struct sockaddr *)serveraddr,serveraddr_len);五、套接字设置成被动监听listen函数 int ret1 listen(sock_fd, 5);六、创建红黑树epoll_create函数 #include sys/epoll.hint epoll_create(int size);/*功能创建epoll/创建epoll实例的描述符参数size:参数已经被忽略了只需要填写大于0的值即可返回值epoll_create 调用成功时会返回一个非负整数epfd表示新创建的 epoll 实例的文件描述符如果调用失败则返回 -1并设置 errno 变量以指示具体错误原因*/int epfd epoll_create(1);if(-1 epfd){perror(epoll_create error);exit(-1);}七、定义事件结构体变量和存放就绪事件描述符的数组事件结构体epoll_event用于描述一个文件描述符上的事件 typedef union epoll_data {void *ptr;int fd; uint32_t u32;uint64_t u64;} epoll_data_t; struct epoll_event {uint32_t events; //EPOLLIN 读 / EPOLLOUT 写epoll_data_t data; //存放用户的数据}; struct epoll_event event;struct epoll_event events[N];八、将关心的文件描述符加入到红黑树epoll_ctl函数功能epoll的控制操作或者用于向 epoll 实例中添加、修改、删除事件epoll_ctl函数 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);/*参数epfd:epoll的文件描述符op:控制方式EPOLL_CTL_ADD添加EPOLL_CTL_MOD修改EPOLL_CTL_DEL删除fd:被操作的文件描述符event:事件结构体指针返回值 成功返回0失败返回-1 置位错误码*///添加要检测事件的描述符event.events EPOLLIN;event.data.fd sock_fd;//将关心的文件描述符加入到红黑树if(-1 (epoll_ctl(epfd,EPOLL_CTL_ADD,sock_fd,event))){perror(epoll_ctl error);exit(-1);}九、等待文件描述符中的事件是否就绪成功则返回就绪的文件描述符的个数epoll_wait函数epoll_wait函数 int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);/*参数epfd:epoll的文件描述符events:准备好的事件的结构体地址maxevents:返回的最大的文件描述符的个数timeout:超时0 :毫秒级别的超时时间0 :立即返回-1:不关心超时时间返回值成功返回准备好的文件描述符的个数返回0代表超时时间到了失败返回-1置位错误码*/if(-1 (ret epoll_wait(epfd,events,N,-1))){perror(epoll_wait error);exit(-1);} 十、遍历就绪的文件描述符集判断哪些文件描述符已经准备就绪 for(int i 0; i ret; i){...}十一、找到实际就绪的事件的文件描述符并且接收来自客户端的数据recv函数和给客户端发送应答消息send函数 if(events[i].data.fd sock_fd){//获取连接成功后新的客户端new_fd accept(sock_fd,(struct sockaddr *)clientaddr,clientaddr_len);if(-1 new_fd){perror(accept error);exit(-1);}printf(文件描述符[%d]客户端[%s:%d]连接到了服务器\n,new_fd,inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));//添加要检测的文件描述符event.events EPOLLIN;event.data.fd new_fd;if(-1 (epoll_ctl(epfd,EPOLL_CTL_ADD,new_fd,event))){perror(epoll_ctl error);exit(-1);}printf(文件描述符[%d]成功挂载在红黑树上\n,new_fd);}else{memset(buf,0,sizeof(buf));int old_fd events[i].data.fd;if(-1 (nbytes recv(old_fd,buf,sizeof(buf),0))){perror(recv error);exit(-1);}else if(0 nbytes){printf(文件描述符[%d]客户端断开了服务器\n,old_fd);//关闭对应的文件描述符close(old_fd);//剔除挂在树上对应的文件描述符epoll_ctl(epfd,EPOLL_CTL_DEL,old_fd,event);}if(!strncmp(buf,quit,4)){printf(文件描述符[%d]客户端退出了服务器\n,old_fd);//关闭对应的文件描述符close(old_fd);//剔除挂在树上对应的文件描述符epoll_ctl(epfd,EPOLL_CTL_DEL,old_fd,event);}printf(文件描述符[%d]客户端发来数据[%s]\n,old_fd,buf);//组装应答消息strcat(buf,-----k);//给客户端发送应答消息send(old_fd,buf,sizeof(buf),0); 十二、关闭套接字close函数 close(sock_fd);