一般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; }
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.要發送數據包再立即接收響應
