C语言 poll多路复用


NAME
       poll, ppoll - wait for some event on a file descriptor

SYNOPSIS
       #include <poll.h>

函数原型:       

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

       #define _GNU_SOURCE         /* See feature_test_macros(7) */
       #include <signal.h>
       #include <poll.h>

函数功能:

                同时监听多个阻塞线程或进程的函数。

参数

        参数一:今天元素数组;

                        struct pollfd{  
                                    int     fd;         /* 文件描述符 */  
                                    short   events;     /* 等待的事件 */  
                                     short   revents;    /* 实际发生了的事件 */
                                   } ;

                       每一个pollfd结构体指定了一个被监视的文件描述符fd,指示poll()监视多个文件描述符。每个结构体的 events 域是监视该文件描述符的事件掩码,由用户来设置这个域。        ​​        revents 域是文件描述符的操作结果事件掩码,内核在调用返回时设置这个域,events 域中请求的任何事件都可能在revents域中返回。下表列出指定 events 标志以 及测试 revents 标志的一些常值。

        参数二:nfds_t nfds  指定数组中监听的元素个数;

        参数三: timeout指定等待的毫秒数,无论I/O是否准备好,poll都会返回。timeout指定为负数值表示无限超时,使poll() 一直挂起直到一个指定事件发生;timeout为0指示poll调用立即返回并列出准备好I/O的文件描述符,但并不等待其它的事件。 这种情况下,poll()就像它的名字那样,一旦选举出来,立即返回

        返回值:

        该函数成功调用时,poll()返回结构体中revents域不为0的文件描述符个数;如果在超时前没有任何事件发生,poll()返回0; 失败时,poll()返回-1,并设置errno为下列值之一:

  • EBADF   一个或多个结构体中指定的文件描述符无效。
  • EFAULTfds   指针指向的地址超出进程的地址空间。
  • EINTR     请求的事件之前产生一个信号,调用可以重新发起。
  • EINVALnfds  参数超出PLIMIT_NOFILE值。
  • ENOMEM   可用内存不足,无法完成请求。
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netinet/ip.h>
    #include <sys/types.h>
    #include <stdio.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <pthread.h>
    #include <string.h>
    #include <sys/time.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/select.h>
    #include <signal.h>
    #include <poll.h>
    struct sockaddr_in cli_addr[2];
    int cli_fb[2];
    
    int main(int argc, char const *argv[])
    {
        // 1、创建socket
        int fb = socket(AF_INET, SOCK_STREAM, 0);
        if (fb < 0)
        {
            perror("socket");
            return 0;
        }
        // 绑定地址
        struct sockaddr_in addr;                  // 定义结构体
        addr.sin_family = AF_INET;                // 设置为IPV4
        addr.sin_port = htons(8977);              // 设置端口号为8080  htons():将本地网络字序改为网络传输统一的大端存储的字序
                                                  // ntohs() 将网络字序转化为本地主机字序
        addr.sin_addr.s_addr = htonl(INADDR_ANY); // 设置网络IP    inet_addr():将字符串转化为整型地址
        // 2、绑定socket
        if (bind(fb, (struct sockaddr *)&addr, sizeof(addr)) == 0)
        {
            perror("bind");
        }
        else
        {
            perror("bind fail");
        }
    
        // 3、设置监听,,模式
        if (listen(fb, 3))
        {
            perror("listen");
        }
    
        while (1)
        {
    
            // 多路复用
            struct pollfd fbp[2];
            fbp[0].fd = 0;
            fbp[0].events = POLLIN;
            fbp[1].fd = fb;
            fbp[1].events = POLLIN;
            struct timeval timeout;
            timeout.tv_sec = 10;
            timeout.tv_usec = 0;
    
            // 开始监听服务器
            int ret = poll(fbp, 2, -1);
            if (ret > 0)
            {
                printf("有人活跃\n");
    
                if (fbp[0].revents & POLLIN)
                {
                    printf("键盘活跃\n");
                    char msg[100];
                    read(fbp->fd, msg, sizeof(msg));
                    if (msg[0] == '1')
                    {
                        break;
                    }
    
                    printf("%s\n", msg);
                }
                if (fbp[1].revents & POLLIN)
                {
                    printf("客户活跃\n");
                    int fbap = accept(fbp[1].fd, NULL, NULL);
                    if (fbap < 0)
                    {
                        perror("accept");
                        close(fbap);
                    }
                }
            }
        }
        close(fb);
        return 0;
    }
    

    这段代码用于监听是否TCP客户端连接,并监听系统标准输出;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值