第6章 I/O复用:select和poll函数
来源:互联网 发布:2017fc2破解版域名设置 编辑:程序博客网 时间:2024/05/02 02:34
I/O复用:一种预先告知内核的能力,使得内核一旦发现进程指定的一个或多个I/O条件就绪,它就通知进程。
同步I/O:导致请求的进程阻塞,直到I/O操作完成。
异步I/O:不导致请求进程阻塞。
I/O复用模型(select、poll):
5种I/O模型比较:
/* According to POSIX.1-2001, POSIX.1-2008 */#include <sys/select.h> /* According to earlier standards */ #include <sys/time.h> #include <sys/types.h> #include <unistd.h>int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);void FD_CLR(int fd, fd_set *set);int FD_ISSET(int fd, fd_set *set);void FD_SET(int fd, fd_set *set);void FD_ZERO(fd_set *set);#include <sys/select.h>int pselect(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, const struct timespec *timeout,const sigset_t *sigmask);/* Feature Test Macro Requirements for glibc (see feature_test_macros(7)):pselect(): _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600*/
select客户端:
#include "../Gnet.h"void do_client(int connfd){ char buf[MAX_LINE]; int maxfd; fd_set rset; int n; int closewr; closewr = 0; while(1) { FD_ZERO(&rset); if(closewr == 0) FD_SET(STDIN_FILENO, &rset); FD_SET(connfd, &rset); maxfd = STDIN_FILENO > connfd ? STDIN_FILENO : connfd; if(select(maxfd+1, &rset, NULL, NULL, NULL) < 0) perr_exit("select error."); if(FD_ISSET(connfd, &rset)) { if((n = Read(connfd, buf, MAX_LINE)) == 0) { if(closewr == 1) return; else perr_exit("server terminated."); } Write(STDOUT_FILENO, buf, n); } if(FD_ISSET(STDIN_FILENO, &rset)) { if((n = Read(STDIN_FILENO, buf, MAX_LINE)) == 0) { shutdown(connfd, SHUT_WR); FD_CLR(STDIN_FILENO, &rset); closewr = 1; } else Write(connfd, buf, n); } }}int main(int argc, const char* argv[]){ int connfd; struct sockaddr_in server_addr; if(argc < 2) perr_exit("usage : client <IPaddress>"); connfd = Socket(AF_INET, SOCK_STREAM, 0); memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(SERVER_PORT); inet_pton(AF_INET, argv[1], &server_addr.sin_addr); Connect(connfd, (struct sockaddr*)&server_addr, sizeof(server_addr)); do_client(connfd); return 0;}
select服务器:
#include "../Gnet.h"int main(int argc, const char* argv[]){ int lfd, connfd; int maxfd; int client[FD_SETSIZE], maxi, findi; int nready; int nread; struct sockaddr_in server_addr, client_addr; socklen_t client_addr_len; fd_set allset, rset; char buf[MAX_LINE]; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(SERVER_PORT); lfd = Socket(AF_INET, SOCK_STREAM, 0); Bind(lfd, (const struct sockaddr*)&server_addr, sizeof(server_addr)); Listen(lfd, LISTENQ); maxfd = lfd; maxi = -1; for(int i=0; i<FD_SETSIZE; ++i) client[i] = -1; FD_ZERO(&allset); FD_SET(lfd, &allset); printf("waiting for connecting.\n"); while(1) { rset = allset; nready = select(maxfd+1, &rset, NULL, NULL, NULL); if(nready < 0) perr_exit("select error."); if(FD_ISSET(lfd, &rset)) { client_addr_len = sizeof(client_addr); connfd = Accept(lfd, (struct sockaddr*)&client_addr, &client_addr_len); for(findi = 0; findi < FD_SETSIZE; ++findi) { if(client[findi] < 0) { client[findi] = connfd; break; } } if(findi == FD_SETSIZE) Close(connfd); else { FD_SET(connfd, &allset); if(connfd > maxfd) maxfd = connfd; if(findi > maxi) maxi = findi; if(--nready <= 0) continue; } } for(int i=0; i <= maxi; ++i) { if(client[i] < 0) continue; if(FD_ISSET(client[i], &rset)) { if((nread = Read(client[i], buf, MAX_LINE)) == 0) { Close(client[i]); FD_CLR(client[i], &allset); client[i] = -1; } else Write(client[i], buf, nread); if(--nready <= 0) break; } } } return 0;}
#include <poll.h> int poll(struct pollfd *fds, nfds_t nfds, int timeout); #define _GNU_SOURCE /* See feature_test_macros(7) */ #include <signal.h> #include <poll.h> int ppoll(struct pollfd *fds, nfds_t nfds, const struct timespec *tmo_p, const sigset_t *sigmask);
poll服务器:
#include "../Gnet.h"int main(int argc, const char* argv[]){ int lfd, connfd; int maxi, findi; int nready; int nread; struct sockaddr_in server_addr, client_addr; socklen_t client_addr_len; char buf[MAX_LINE]; struct pollfd client[OPEN_MAX]; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(SERVER_PORT); lfd = Socket(AF_INET, SOCK_STREAM, 0); Bind(lfd, (const struct sockaddr*)&server_addr, sizeof(server_addr)); Listen(lfd, LISTENQ); client[0].fd = lfd; client[0].events = POLLRDNORM; for(int i=1; i<OPEN_MAX; ++i) client[i].fd = -1; maxi = 0; printf("waiting for connecting.\n"); while(1) { nready = poll(client, maxi+1, -1); if(nready < 0) perr_exit("poll error."); if(client[0].revents & POLLRDNORM) { client_addr_len = sizeof(client_addr); connfd = Accept(lfd, (struct sockaddr*)&client_addr, &client_addr_len); for(findi=1; findi<OPEN_MAX; ++findi) { if(client[findi].fd < 0) { client[findi].fd = connfd; break; } } if(findi == OPEN_MAX) Close(connfd); else { if(findi > maxi) maxi = findi; client[findi].events = POLLRDNORM; if(--nready <= 0) continue; } } for(int i =1; i <= maxi; ++i) { if(client[i].fd < 0) continue; if(client[i].revents & (POLLRDNORM | POLLERR)) { if((nread = Read(client[i].fd, buf, MAX_LINE)) < 0) { client[i].fd = -1; printf("read error."); } else if(nread == 0) { Close(client[i].fd); client[i].fd = -1; } else Write(client[i].fd, buf, nread); if(--nready <= 0) break; } } } return 0;}
github:https://github.com/gongluck/CodeBase/tree/master/notes/unpv13-notes
阅读全文
0 0
- 第6章:I/O复用:select和poll函数
- 第6章 I/O复用:select和poll函数
- Unix网络编程代码 第6章 I/O复用:select、poll和epoll函数
- Unix网络编程学习笔记之第6章 I/O复用:select和poll函数
- I/O复用:Select和Poll函数
- I/O复用 select和poll函数
- I/O复用:select和poll函数
- 第六章:I/O复用:select和poll函数
- 第六章:I/O复用2:select和poll函数
- UNP第六章 I/O复用:select和poll函数
- [UNP笔记]I/O复用,select和poll函数
- I/O复用:select和poll函数(一)
- UNIX 网络编程 卷一:套接字联网API(第3版) 读书笔记(6) 第六章 I/O复用:select和poll函数
- 6 I/O复用:select and poll函数
- i/o复用 select和poll用法
- Linux I/O 模型---I/O复用:Select和Poll函数
- Linux I/O 模型---I/O复用:Select和Poll函数
- Unix下五种I/O模型(中文图片) I/O复用:Select和Poll函数
- ASM概念
- Python For Kids学习笔记03:Strings, Lists, Tuples, and Maps
- java——log4j生成日志文件
- Android中RecyclerView的item中控件的点击事件添加删除一行、上移下移一行的代码实现
- Linux下安装Erlang
- 第6章 I/O复用:select和poll函数
- hadoop(1)ssh连接与hadoop搭建
- 6.5
- n个十六进制转化为八进制
- CSS布局
- GIS前端获取后台数据库在Popup中显示
- UIImageView 平滑过渡图片切换
- Java I/O系统之OutputStream
- 遍历c:\windows