linux 多路复用---poll

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 }
复制代码

客户端不变

posted on   廿陆  阅读(36)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示