linux并发服务器模型四、poll

linux并发服务器模型四、pollintpoll;fds[]数组地址,select需要一张表,而这里需要一个结构体数组,每个结构体中有一个fdnfds需要检测文件描述符对应结构体在数组中的下标+1,表示一个检测的范围timeout1.-1永久阻塞2.0:调用完成立即返回3.

大家好,欢迎来到IT知识分享网。

相对于select做了一些改进, 突破了1024, select是需要一张表, 并且需要遍历其中改变的描述符

而poll将这些内容封装成一个结构体, 其中包含了fd和需要监控的事件, 如果发生改变则会更改revents值

 struct pollfd { int fd; // 文件描述符 short events; // 监控的事件 short revents;// 监控事件中满足条件返回的事件 }; int poll(struct pollfd fds[], nfds_t nfds, int timeout); fds[] 数组地址, select需要一张表, 而这里需要一个结构体数组, 每个结构体中有一个fd nfds 需要检测文件描述符对应结构体在数组中的下标+1, 表示一个检测的范围 timeout 1.-1 永久阻塞 2.0:调用完成立即返回 3.>0: 等待的时长, 毫秒 返回值:IO发生变化的文件描述符的个数 

server

#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <string.h> #include <arpa/inet.h> #include <sys/socket.h> #include <poll.h> #include <ctype.h> #define SERV_PORT 8888 int main(int argc, const char * argv[]) { int lfd, cfd; //用于监听和通信的文件描述符 struct sockaddr_in serv_addr, clien_addr;//sockaddr结构体 //结构体长度 socklen_t serv_len = sizeof(serv_addr), clien_len = sizeof(clien_addr); //创建套接字 lfd = socket(AF_INET, SOCK_STREAM, 0); //初始化服务器 serv_addr memset(&serv_addr, 0, serv_len); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);//所有IP serv_addr.sin_port = htons(SERV_PORT);//设置端口 //设置重用端口 int opt = 1; setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); //绑定IP和端口 bind(lfd, (struct sockaddr*)&serv_addr, serv_len); // 设置同时监听的最大个数 listen(lfd, 64); printf("Start accept ......\n"); //poll结构体数组 struct pollfd allfd[1024]; int max_index = 0; // nfds 检测的范围时用 //初始化结构体数组, 将监听事件设置为POLLIN, 并且从lfd开始监听 for (int i = 0; i < 1024; ++i) { allfd[i].fd = -1; //初始化成无效的值 allfd[i].events = POLLIN; //如果需要监听其他的则赋值对应的宏即可 } allfd[0].fd = lfd; //默认从lfd之后的文件描述符开始监听 int i = 0; while (1) { //第一次只有一个-lfd, 主要用于检测有没有新的客户端连接 int ret = poll(allfd, max_index+1, -1); if (ret == -1) { perror("poll error"); exit(1); } //判断有没有客户端连接 if (allfd[0].revents & POLLIN) { //接受连接请求 cfd = accept(lfd, (struct sockaddr *)&clien_addr, &clien_len); char ipbuf[128]; printf("new client link IP: %s, port: %d\n", inet_ntop(AF_INET, &clien_addr.sin_addr.s_addr, ipbuf, sizeof(ipbuf)), ntohs(clien_addr.sin_port)); //将刚刚接受的连接请求对应的客户端的文件描述符加到数组中 for (int i = 0; i < 1024; ++i) { if (allfd[i].fd == -1) { allfd[i].fd = cfd; break; } } i++; //更新要监听的范围 max_index = max_index < i ? i : max_index; } //遍历数组, 查看发生改变的客户端, 并做出对应操作 //从1开始监听, 因为0位置的是lfd for (int i = 1; i <= max_index; ++i) { int fd = allfd[i].fd; if(fd == -1) { continue; } if(allfd[i].revents & POLLIN) { //接受数据 char buf[1024] = {0}; int len = (int)recv(fd, buf, sizeof(buf), 0); if(len == -1) { perror("recv error"); exit(1); } else if(len == 0) { allfd[i].fd = -1; //重新置为无效, 系统检测到无效的话会跳过 close(fd); printf("客户端已经主动断开连接。。。\n"); } else { printf("recv buf = %s\n", buf); for(int k = 0; k < len; ++k) { buf[k] = toupper(buf[k]); //变为大写 } printf("buf toupper: %s\n", buf); send(fd, buf, strlen(buf)+1, 0); } } } } return 0; } 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/85167.html

(0)
上一篇 2024-09-28 16:33
下一篇 2024-09-29 05:35

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信