linux poll 学习
一、poll介绍
函数原型:
#include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd定义:
struct pollfd { int fd; /* file descriptor */ short events; /* requested events */ short revents; /* returned events */ };
fd:文件描述符
events:关心的事件,输入参数
revents:产生的事件,输出参数
事件类型:
POLLIN 普通或优先级带数据可读
POLLRDNORM 普通数据可读
POLLRDBAND 优先级带数据可读
POLLPRI 高优先级数据可读
POLLOUT 普通数据可写
POLLWRNORM 普通数据可写
POLLWRBAND 优先级带数据可写
POLLERR 发生错误
POLLHUP 发生挂起
POLLNVAL 描述字不是一个打开的文件
关于poll的具体用法,请见下面示例。
二、poll使用
示例1:回显服务器
/******************************************************************************* * File Name : poll.cpp * Author : zjw * Email : emp3XzA3MjJAMTYzLmNvbQo= (base64 encode) * Create Time : 2015年07月17日 星期五 09时42分11秒 *******************************************************************************/ #include <sys/types.h> #include <sys/socket.h> #include <poll.h> #include <netinet/in.h> #include <unistd.h> #include <arpa/inet.h> #include <iostream> #include <cstdio> #include <cstdlib> #include <cerrno> #include <cstring> using namespace std; const int SERVER_PORT = 8080; const int EVENT_SIZE = 1024; const int RECV_SIZE = 1024; const int SEND_SIZE = 1040; int main(int argc, char **argv) { int server = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in addrServer; bzero(&addrServer, sizeof(addrServer)); addrServer.sin_family = AF_INET; addrServer.sin_port = htons(SERVER_PORT); addrServer.sin_addr.s_addr = INADDR_ANY; if (bind(server, (struct sockaddr*)&addrServer, sizeof(addrServer))) { perror("bind failed,"); return -1; } listen(server, 10); cout << "listening on port:" << SERVER_PORT << " ..." << endl; struct pollfd fds[EVENT_SIZE] = {{0, 0, 0}}; fds[server].fd = server; fds[server].events = POLLIN; int ret = 0; char recvBuf[RECV_SIZE + 1]; char sendBuf[SEND_SIZE + 1]; while (1) { if ((ret = poll(fds, EVENT_SIZE, 0)) < 0) { perror("poll failed,"); return -1; } for (int i = 0; i < EVENT_SIZE; i++) { if (fds[i].fd == 0) { continue; } if (fds[i].fd == server && (fds[i].revents & POLLIN)) { // accept a new client struct sockaddr_in addrClient; socklen_t len = sizeof(addrClient); int client = accept(server, (struct sockaddr*)&addrClient, &len); if (client == -1) { perror("accept failed,"); return -1; } else { cout << "accep an new client " << client << ", ip:" << inet_ntoa(addrClient.sin_addr) << endl; fds[client].fd = client; fds[client].events = POLLIN; } } else if (fds[i].revents & POLLIN) { // read event memset(recvBuf, 0, RECV_SIZE + 1); if ((ret = recv(fds[i].fd, recvBuf, RECV_SIZE, 0)) < 0) { perror("recv failed,"); return -1; } else if (ret == 0) { // client close close(fds[i].fd); fds[i].fd = 0; } else { // recv data cout << "client " << fds[i].fd << " said:" << recvBuf << endl; memset(sendBuf, 0, SEND_SIZE + 1); sprintf(sendBuf, "You said:%s", recvBuf); if ((ret = send(fds[i].fd, sendBuf, SEND_SIZE, 0)) < 0) { perror("send failed,"); return -1; } } } else { // write event } } } close(server); return 0; }
Makefile:
echo: poll.cpp g++ -g -o $@ $< clean: rm -rf echo
运行结果:
服务器端:
客户端1:
客户端2:
三、参考
http://www.360doc.com/content/12/0821/10/7775902_231465100.shtml
http://blog.chinaunix.net/uid-23842323-id-2656589.html