linux系统编程之poll函数使用案例

    科技2022-08-26  100

    #include<unistd.h> #include<sys/socket.h> #include<netinet/in.h> #include <strings.h> #include<error.h> #include <errno.h> #include<stdio.h> #include<stdlib.h> #include<signal.h> #include <sys/wait.h> #include<limits.h> #include<poll.h> #include<features.h> #define INFTIM -1 const int OPEN_MAX=1024; int main(int argc, char **argv) { int i, maxi, listenfd, connfd, sockfd; int nready; ssize_t n; char buf[1024]; char str[100]; socklen_t clilen; struct pollfd client[OPEN_MAX]; struct sockaddr_in cliaddr, servaddr; listenfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(2000); bind(listenfd, (sockaddr *) &servaddr, sizeof(servaddr)); listen(listenfd, 5); /*初始化准备工作,将第一个数组下标监听套接字读事件*/ client[0].fd = listenfd; client[0].events = POLLRDNORM;//POLLRDNORM需要定义头文件features.h,否则报错 for (i = 1; i < OPEN_MAX; i++) client[i].fd = -1; /* 将剩下的数组描述符全部置为-1,方便以后判断操作 */ maxi = 0; /* 这个值用来寻找对比数组下标,以及poll监听的数量 */ while (1) { nready = poll(client, maxi+1, INFTIM); if (client[0].revents & POLLRDNORM) { /* 如果套接字有读事件则调用accept */ clilen = sizeof(cliaddr); connfd = accept(listenfd, (sockaddr *) &cliaddr, &clilen); /*找到合适的数组下标存放accept的描述符,监听accept读事件*/ for (i = 1; i < OPEN_MAX; i++) if (client[i].fd < 0) { client[i].fd = connfd; //accept的返回的描述符 client[i].events = POLLRDNORM; //监听读事件 break; } /*接下来的三个判断,健壮性代码 1-判断是否已经到达最大数组,防止越界 2-将数组下标赋值给maxi,方便在下半区代码遍历寻找,以及控制poll监听数量 3-如果监听事件为套接字,则没有必要对下半区代码进行操作,所以设计--nready==0 */ if (i == OPEN_MAX)//最大下标 { perror("too many clients"); exit(0); } if (i > maxi)//数组当前下标以及poll监听数量 maxi = i; /* 只有当poll的返回值大于等于2才会执行下半区代码 意思为当poll监听套接字以及accept两个描述符才会i执行下半区代码 */ if (--nready <= 0)// continue; } /*------下半区代码是用来监听accept的读事件--------*/ for (i = 1; i <= maxi; i++) { /* 遍历寻找监听accept的pollfd数组下标 */ if ( (sockfd = client[i].fd) < 0) continue; /*如果当前下标有accept读事件则进行以下操作*/ if (client[i].revents & (POLLRDNORM | POLLERR)) { if ( ( n = read(sockfd, buf, 1024)) < 0) { if (errno == ECONNRESET) { /*客户端重置连接 */ close(sockfd); client[i].fd = -1; } else perror("read error"); } else if (n == 0) { /*n==0表示客户端关闭,关闭描述符,将数组fd置为-1 */ close(sockfd); client[i].fd = -1; } else write(sockfd, buf, n); if (--nready <= 0) break; /* 没有更多的描述符,退出当前循环 */ } } } }
    Processed: 0.016, SQL: 9