linux高性能服务器编程---第九章 I/O复用 (2)
poll
#include <poll.h> // fds 结构体类型数组 指定我们感兴趣的文件描述符上发生的可读可写和异常事件\ // nfds 遍历结合大小 左闭右开 // timeout 单位为毫秒 -1 为阻塞 0 为立即返回 int poll(struct pollfd* fds, nfds_t nfds, int timeout); struct pollfd { int fd; short events; //注册的事件, 告知poll监听fd上的哪些事件 short revents; // 实际发生的事件 }
#define exit_if(r, ...) \ { \ if (r) \ { \ printf(__VA_ARGS__); \ printf("errno no: %d, error msg is %s", errno, strerror(errno)); \ exit(1); \ } \ } \ struct client_info { char *ip_; int port_; }; int main(int argc, char* argv[]) { int port = 8001; char ip[] = "127.0.0.1"; struct sockaddr_in address; address.sin_port = htons(port); address.sin_family = AF_INET; address.sin_addr.s_addr = htons(INADDR_ANY); int listenfd = socket(PF_INET, SOCK_STREAM, 0); exit_if(listenfd < 0, "socket error\n"); int ret = bind(listenfd, (struct sockaddr*)&address, sizeof(address)); exit_if(ret == -1, "bind error\n"); ret = listen(listenfd, 5); exit_if(ret == -1, "listen error\n"); constexpr int MAX_CLIENTS = 1024; struct pollfd polls[MAX_CLIENTS] = {}; struct client_info clientsinfo[MAX_CLIENTS] = {}; polls[3].fd = listenfd; polls[3].events = POLLIN | POLLRDHUP; while (true) { ret = poll(polls, MAX_CLIENTS + 1, -1); exit_if(ret == -1, "poll error\n"); for (int i = 3; i <= MAX_CLIENTS; ++i) { int fd = polls[i].fd; if (polls[i].revents & POLLRDHUP) { polls[i].events = 0; printf("close fd-%d from %s:%d\n", fd, clientsinfo[fd].ip_, clientsinfo[fd].port_); } if (polls[i].revents & POLLIN) { if (fd == listenfd) { struct sockaddr_in client_address; socklen_t client_addresslen = sizeof(client_address); int clientfd = accept(listenfd, (struct sockaddr*)&client_address, &client_addresslen); struct client_info *clientinfo = &clientsinfo[clientfd]; clientinfo->ip_ = inet_ntoa(client_address.sin_addr); clientinfo->port_ = ntohs(client_address.sin_port); exit_if(clientfd < 0, "accpet error, from %s:%d\n", clientinfo->ip_, clientinfo->port_); printf("accept from %s:%d\n", clientinfo->ip_, clientinfo->port_); polls[clientfd].fd = clientfd; polls[clientfd].events = POLLIN | POLLRDHUP; } else { char buffer[1024]; memset(buffer, '\0', sizeof(buffer)); ret = read(fd, buffer, 1024); if(ret == 0) { close(fd); } else { printf("recv from %s:%d:\n%s\n", clientsinfo[fd].ip_, clientsinfo[fd].port_, buffer); } } } } } }