linux 多路复用---poll
1.linux socket地址2.linux IP 地址转换3.linux TCP 通信流程 套接字函数 socket() bind() listen() accept() connect()4.linux TCP通信实现 服务器端 - 客户端5.linux TCP 三次握手6.linux TCP滑动窗口 四次挥手7.linux 多进程实现并发服务器 多线程并发8.linux TCP状态转换 半关闭 shutdown netstat 端口复用 setsockopt9.linux IO多路复用 select poll epoll
10.linux 多路复用---poll
11.linux 多路复用---epoll12.linux UDP 通信13.linux 本地套接字通信14.linux Web服务器以及HTTP协议15.linux 服务器编程基本框架和两种高效事件的处理模式16.linux 线程池 EPOLLONESHOT事件poll定义:
/* #include <poll.h> struct pollfd { int fd; //委托内核检测的文件描述符 short events; //委托内核检测文件描述符的什么事件 short revents; //文件描述符实际发生的事件(返回的事件) }; //struct pollfd myfd; //myfd.fd = 5; //myfd.events = POLLIN | POLLOUT; int poll(struct pollfd *fds, nfds_t nfds, int timeout); - 参数: - fds: 是一个 struct pollfd 结构体数组, 这是一个需要检测的文件描述符的集合 - nfds: 这个是第一个参数数组中组后一个游戏元素的下标 + 1 - timeout: 阻塞时长 0: 不阻塞 -1: 阻塞,当检测到需要检测的文件描述符有变化,解除阻塞 >0: 阻塞的时长 - 返回值: -1: 失败 >0(n): 成功, n表示检测到集合中有n个文件描述符发生变化 */
poll服务器端:
1 #include <stdio.h> 2 #include <arpa/inet.h> 3 #include <unistd.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <poll.h> 7 int main() 8 { 9 //创建 socket 10 int lfd = socket(PF_INET, SOCK_STREAM, 0); 11 struct sockaddr_in saddr; 12 saddr.sin_port = htons(9999); 13 saddr.sin_family = AF_INET; 14 saddr.sin_addr.s_addr = INADDR_ANY; 15 //绑定 16 bind(lfd, (struct sockaddr *)&saddr, sizeof(saddr)); 17 //监听 18 listen(lfd, 8); 19 //初始化检测的文件描述符数组 20 struct pollfd fds[1024]; 21 for(int i = 0; i < 1024; i++) 22 { 23 fds[i].fd = -1; 24 fds[i].events = POLLIN;//检测读事件 25 } 26 fds[0].fd = lfd; 27 int nfds = 0; 28 while(1) 29 { 30 //调用 poll系统函数,让内核帮助检测哪些文件描述符有数据 31 int ret = poll(fds, nfds + 1, -1); 32 if(ret == -1) 33 { 34 perror("poll"); 35 exit(-1); 36 } 37 else if(ret == 0) 38 { 39 continue; 40 } 41 else if(ret > 0) 42 { 43 //说明检测到了有文件描述符的对应的缓冲区的数据发生了改变 44 if(fds[0].revents & POLLIN) 45 { 46 //表示有新的客户端连接进来了 47 struct sockaddr_in cliaddr; 48 int len = sizeof(cliaddr); 49 int cfd = accept(lfd, (struct sockaddr *)&cliaddr, &len); 50 //将新的文件描述符加入到集合中 51 for(int i = 1; i < 1024; i++) 52 { 53 if(fds[i].fd == -1) 54 { 55 fds[i].fd = cfd; 56 fds[i].events = POLLIN; 57 break; 58 } 59 } 60 //更新最大的文件描述符的索引 61 nfds = nfds > cfd ? nfds : cfd; 62 } 63 for(int i = 1; i <= nfds; i++) 64 { 65 if(fds[i].revents & POLLIN) 66 { 67 //说明这个文件描述符对应的客户端发来了数据 68 char buf[1024] = {0}; 69 int len = read(fds[i].fd, buf, sizeof(buf)); 70 if(len == -1) 71 { 72 perror("read"); 73 exit(-1); 74 } 75 else if( len == 0) 76 { 77 printf("client closed...\n"); 78 close(fds[i].fd); 79 fds[i].fd = -1; 80 } 81 else if(len > 0) 82 { 83 printf("read buf = %s\n",buf); 84 write(fds[i].fd, buf, strlen(buf) + 1); 85 } 86 } 87 } 88 } 89 } 90 close(lfd); 91 return 0; 92 }
客户端不变
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)