一般poll使用过程中都是检测POLLIN事件,表示描述符有事件可以处理了,需要我们处理。对POLLOUT事件触发的方式相对较少,网上也有很多对此触发的疑问,利用实际项目中用的一个用法,下面做了个测试,

struct pollfd {  

      int fd;        //文件描述符  

      short events;  //要求查询的事件掩码  

      short revents; //返回的事件掩码  

};  

int poll(struct pollfd *ufds, unsigned int nfds, int timeout);  

     poll函数使用pollfd类型的结构来监控一组文件句柄,ufds是要监控的文件句柄集合,nfds是监控的文件句柄数量,timeout是等待的毫秒数,这段时间内无论I/O是否准备好,poll都会返回。timeout为负数表示无线等待,timeout为0表示调用后立即返回。执行结果:为0表示超时前没有任何事件发生;-1表示失败;成功则返回结构体中revents不为0的文件描述符个数

#define POLLIN 0x0001 /* There is data to read */
#define POLLPRI 0x0002 /* There is urgent data to read */
#define POLLOUT 0x0004 /* Writing now will not block */
#define POLLERR 0x0008 /* Error condition */
#define POLLHUP 0x0010 /* Hung up */
#define POLLNVAL 0x0020 /* Invalid request: fd not open */

#include <poll.h>
#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <string.h>

int main()
{
     struct pollfd pfd;
     int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
     int nonblocking = 1;

     int flags = fcntl(fd, F_GETFL, 0);                  //获取文件的flags值。
     int ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);   //设置成非阻塞模式;

    struct sockaddr_in serv_addr;
    memset(&serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(443); //测试的服务端口
    //serv_addr.sin_addr.s_addr = htonl("127.0.0.1"); //本地所有的IP
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    printf("fd:%d,ret:%d\n",fd,ret);

    if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) != 0 && errno == EINPROGRESS) {
         printf("err connect:%s\n", strerror(errno));
         while (1) {
           if (connect(fd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) == 0) {
                printf("retry connect success\n");
                break;
           }
        }
     }else {
        printf("connect success, err:%s\n",strerror(errno));
     }
     pfd.fd      = fd;
     //pfd.events  = POLLIN;//POLLIN:0x0001  POLLOUT:0x0004
     pfd.events  = POLLOUT;//POLLIN:0x0001  POLLOUT:0x0004
     pfd.revents = 0;

     ret = poll(&pfd, 1, 100);
     printf("poll ret:%d event:%d, revent:%d, err:%s, errno:%d\n",ret,pfd.events, pfd.revents, strerror(errno));
     return 0;
}
View Code

PULLIN测试结果:

[root@cloud ]#./poll
fd:3,ret:0
err connect:Operation now in progress
retry connect success
poll ret:0 event:1, revent:0, err:Operation now in progress, errno:0   

说明:套接字连接成功之后poll POLLIN事件,poll返回值是0即没有准备好的可读的事件,期望事件和实际轮询的事件不一样。

PULLOUT测试结果:

[root@cloud ]#./poll
fd:3,ret:0
err connect:Operation now in progress
retry connect success
poll ret:1 event:4, revent:4, err:Operation now in progress, errno:0
说明:套接字连接成功之后poll POLLOUT事件,poll返回值是1即表示准备好写,期望事件和实际轮询的事件都是写事件。

 可以应用场景说明:1.队列中只有个待发送的数据包  2.要发送数据包再立即接收响应

posted on 2021-12-02 15:34  人生一世,草木一秋。  阅读(2509)  评论(0编辑  收藏  举报