代码实例
#include <unistd.h> #include <sys/types.h> /* basic system data types */ #include <sys/socket.h> /* basic socket definitions */ #include <netinet/in.h> /* sockaddr_in{} and other Internet defns */ #include <arpa/inet.h> /* inet(3) functions */ #include <stdlib.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <poll.h> /* poll function */ #include <limits.h> #define MAXLINE 10240 #ifndef OPEN_MAX #define OPEN_MAX 40960 #endif void handle(struct pollfd* clients, int maxClient, int readyClient); int main(int argc, char **argv) { int servPort = 6888; // 端口信息 int listenq = 1024; // listen等待的最大文件描述符 int listenfd, connfd; struct pollfd clients[OPEN_MAX]; // poll打开的最大文件描述符 int maxi; socklen_t socklen = sizeof(struct sockaddr_in); // 地址长度 struct sockaddr_in cliaddr, servaddr; // 服务器地址和客户端地址 char buf[MAXLINE]; // bug长度 int nready; // 初始化服务器地址 bzero(&servaddr, socklen); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(servPort); // 创建监听套接字 listenfd = socket(AF_INET, SOCK_STREAM, 0); if (listenfd < 0) { perror("socket error"); } // 保证地址可以重复利用 int opt = 1; if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { perror("setsockopt error"); } // 绑定监听套接字和服务器地址 if(bind(listenfd, (struct sockaddr *) &servaddr, socklen) == -1) { perror("bind error"); exit(-1); } if (listen(listenfd, listenq) < 0) { perror("listen error"); } // clients中的第一个套接字是监听套接字 clients[0].fd = listenfd; // clients中的第一个套接字,我们关心的事件是POLLIN事件 clients[0].events = POLLIN; int i; // 其他套接字置为-1 for (i = 1; i< OPEN_MAX; i++) clients[i].fd = -1; maxi = listenfd + 1; printf("pollechoserver startup, listen on port:%d\n", servPort); printf("max connection is %d\n", OPEN_MAX); for ( ; ; ) { printf("For\n"); // poll 函数,clients集合,最大文件描述符,不超时 nready = poll(clients, maxi + 1, -1); printf("Poll End\n"); //printf("nready is %d\n", nready); if (nready == -1) { perror("poll error"); } // 如果clients中的第一个文件描述符有POLLIN事件 if (clients[0].revents & POLLIN) { // 建立连接,返回已连接套接字 connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &socklen); sprintf(buf, "accept form %s:%d\n", inet_ntoa(cliaddr.sin_addr), cliaddr.sin_port); printf(buf, ""); // 将已连接套接字加入空闲位置,并对POLLIN事件感兴趣 for (i = 0; i < OPEN_MAX; i++) { if (clients[i].fd == -1) { clients[i].fd = connfd; clients[i].events = POLLIN; break; } } // 如果没有空闲位置了,则表明clients集合已经满了,关闭套接字 if (i == OPEN_MAX) { fprintf(stderr, "too many connection, more than %d\n", OPEN_MAX); close(connfd); continue; } if (i > maxi) maxi = i; --nready; } handle(clients, maxi, nready); } } void handle(struct pollfd* clients, int maxClient, int nready) { int connfd; int i, nread; char buf[MAXLINE]; printf("Print\n"); if (nready == 0) return; for (i = 1; i< maxClient; i++) { connfd = clients[i].fd; if (connfd == -1) continue; if (clients[i].revents & (POLLIN | POLLERR)) { nread = read(connfd, buf, MAXLINE);//读取客户端socket流 if (nread < 0) { perror("read error"); close(connfd); clients[i].fd = -1; continue; } if (nread == 0) { printf("client close the connection"); close(connfd); clients[i].fd = -1; continue; } write(connfd, buf, nread);//响应客户端 if (--nready <= 0)//没有连接需要处理,退出循环 break; } } }
poll流程图
poll函数和select函数类似,仍然不是异步的
Poll这里卡住了怎么回事啊