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、创建socketint fb = socket(AF_INET, SOCK_STREAM, 0);if (fb < 0){perror("socket");return 0;}// 绑定地址struct sockaddr_in addr; // 定义结构体addr.sin_family = AF_INET; // 设置为IPV4addr.sin_port = htons(8977); // 设置端口号为8080 htons():将本地网络字序改为网络传输统一的大端存储的字序// ntohs() 将网络字序转化为本地主机字序addr.sin_addr.s_addr = htonl(INADDR_ANY); // 设置网络IP inet_addr():将字符串转化为整型地址// 2、绑定socketif (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客户端连接,并监听系统标准输出;