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客户端连接,并监听系统标准输出;