实现TCP并发服务器之四(poll函数)

来源:互联网 发布:阿莱克丝塔萨 知乎 编辑:程序博客网 时间:2024/05/10 13:59

poll函数类似于select函数,但是它的程序员接口不同,尽管它也可用于任何类型 文件描述符。与select不同,poll不为每个状态(可读,可写,异常状态)构造一个描述符集,而是构造一个pollfd结构数组,每个数组元素指定一个描述符编号以及对其所关心的状态

struct pollfd {int fd;//file descriptor to checkshort events;//events of interest on fdshort revents;//events that occured on fd};
同样实现一个TCP服务器看看。

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<sys/poll.h>#include<limits.h>#define MAX_LISTEN 5#define PORT 1987#define IP "127.0.0.1"#define MAX_POLL 100//#define POLLRDNORM 0x0040int main(){int conn_fd;int sock_fd = socket(AF_INET,SOCK_STREAM,0);if (sock_fd < 0) {perror("create socket failed");exit(1);}struct sockaddr_in addr_client;int client_size = sizeof(struct sockaddr_in);struct sockaddr_in addr_serv;memset(&addr_serv, 0, sizeof(addr_serv));addr_serv.sin_family = AF_INET;addr_serv.sin_port = htons(PORT);addr_serv.sin_addr.s_addr = inet_addr(IP);if (bind(sock_fd,(struct sockaddr *)&addr_serv,sizeof(struct sockaddr_in)) < 0) {perror("bind error");exit(1);}if (listen(sock_fd,MAX_LISTEN) < 0) {perror("listen failed");exit(1);}//int recv_num;int send_num;char recv_buf[100];char send_buf[100];//initial "poll" elementsint i, ready;struct pollfd client[MAX_POLL];client[0].fd = sock_fd;client[0].events = POLLRDNORM;for (i = 1;i < MAX_POLL; i ++) {client[i].fd = -1;}int maxi = 0;while (1) {ready = poll(client, maxi + 1, 0);//create new connectionif (client[0].revents & POLLRDNORM) {conn_fd = accept(sock_fd, (struct sockaddr *)&addr_client, &client_size);if (conn_fd < 0) {perror("accept failed");exit(1);}for (i = 1;i < MAX_POLL;i ++) {if (client[i].fd < 0) {client[i].fd = conn_fd;break;}}if (i == MAX_POLL) {perror("too many clients");exit(1);}if (i > maxi)maxi = i;}//send and receivefor (i = 1; i <= maxi; i ++) {if (client[i].fd >= 0 && (client[i].revents & (POLLRDNORM | POLLERR))) {recv_num = recv(client[i].fd, recv_buf, sizeof(recv_buf), 0);if (recv_num <= 0) {close(client[i].fd);client[i].fd = -1;} else {recv_buf[recv_num] = '\0';memset(send_buf,0,sizeof(send_buf));sprintf(send_buf, "server proc got %d bytes\n", recv_num);send_num = send(client[i].fd, send_buf, strlen(send_buf), 0);if (send_num <= 0) {close(client[i].fd);client[i].fd = -1;}}}}}close(sock_fd);return 0;}

其实poll函数和select函数差不多的,都是在获取可用描述符处等待,只是select的文件描述符数目受限于操作系统内核设定,我感觉poll函数用起来更加方便些,每个人都各有所好吧。接下来再看看epoll函数