1. 程式人生 > 其它 >linux高效能伺服器程式設計---第九章 I/O複用 (2)

linux高效能伺服器程式設計---第九章 I/O複用 (2)

poll

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); } } } } } }