异步I/O select & poll
看问题要抓本质,前戏都是浮云,高潮才是关键!
学东西先抓核心,提纲契领。
Blocking I/O
注意下面两个fd: listenfd
& connfd
listenfd = socket(): create an endpoint for communication bind(listenfd,...): bind a name to a socket listen(listenfd,...): listen for connections on a socket connfd = accept(listenfd,...): accept a connection on a socket read/write(connfd,...)
上述程序会阻塞在 accept 上,直接有一个连接到来。
The accept() system call is used with connection-based socket types (SOCK_STREAM, SOCK_SEQPACKET). It extracts the first connection request on the queue of pending connections for the listening socket, sockfd, creates a new connected socket, and returns a new file descriptor referring to that socket. The newly created socket is not in the listening state. The original socket sockfd is unaffected by this call.
select
select提供异步I/O 多路复用(synchronous I/O multiplexing),人如其名,它可以用从多个文件描述符中select准备好数据的文件描述符进行操作,而不是阻塞在一个文件描述符上。详细的介绍参考APUE。
- FD_ZERO - Clear an fd_set
- FD_ISSET - Check if a descriptor is in an fd_set
- FD_SET - Add a descriptor to an fd_set
- FD_CLR - Remove a descriptor from an fd_set
使用异步I/O的服务端编写思路:
- 先将负责监听的socket (listenfd)加入read_fd_set,因为服务端接收连接请求,是读listenfd。
- 每accept一个连接,就返回一个新的连接socket(connfd),connfd可以读写数据,将connfd加入read_fd_set。
listenfd = socket() bind(listenfd,...) listen(listenfd,...) fd_set read_fd_set; FD_SET(listenfd, &read_fd_set) select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) FD_ISSET (i, &read_fd_set) && i==listenfd connfd = accept(listenfd,...) FD_SET(connfd, &read_fd_set) read/write(connfd,...)
poll
poll wait for some event on a file descriptor, it waits for one of a set of file descriptors to become ready to perform I/O.
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd {
int fd; /* file descriptor */
short events; /* requested events */
short revents; /* returned events */
};
event | 意义 |
---|---|
POLLIN | There is data to read. |
POLLPRI | There is urgent data to read (e.g., out-of-band data on TCP socket; pseudoterminal master in packet mode has seen state change in slave). |
POLLOUT | Writing now will not block. |
POLLRDHUP | Stream socket peer closed connection, or shut down writing half of connection. The _GNU_SOURCE feature test macro must be defined (before including any header files) in order to obtain this definition. |
POLLERR | Error condition (output only). |
POLLHUP | Hang up (output only). |
POLLNVAL | Invalid request: fd not open (output only). |
下面是一个用poll写的服务端例子
server example using poll
其实poll和select很类似,都需要不断轮询fd集合,select 通过参数设置read_fd_set和write_fd_set,而poll用pollfd.event的POLLIN或者POLLOUT来判断可读可写。
留下评论