Windows Socket I/O模型以及Linux Epoll模型的有关资料

239 篇文章 2 订阅
106 篇文章 3 订阅
 

本文简单介绍了当前Windows支持的各种Socket I/O模型,如果你发现其中存在什么错误请务必赐教。

一:select模型
二:WSAAsyncSelect模型
三:WSAEventSelect模型
四:Overlapped I/O 事件通知模型
五:Overlapped I/O 完成例程模型


六:IOCP模型

老陈有一个在外地工作的女儿,不能经常回来,老陈和她通过信件联系。他们的信会被邮递员投递到他们的信箱里。
这和Socket模型非常类似。下面我就以老陈接收信件为例讲解Socket I/O模型~~~

一:select模型

老陈非常想看到女儿的信。以至于他每隔10分钟就下楼检查信箱,看是否有女儿的信~~~~~
在这种情况下,"下楼检查信箱"然后回到楼上耽误了老陈太多的时间,以至于老陈无法做其他工作。
select模型和老陈的这种情况非常相似:周而复始地去检查......如果有数据......接收/发送.......

使用线程来select应该是通用的做法:
procedure TListenThread.Execute;
var
addr : TSockAddrIn;
fd_read : TFDSet;
timeout : TTimeVal;
ASock,
MainSock : TSocket;
len, i : Integer;
begin
MainSock := socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
addr.sin_family := AF_INET;
addr.sin_port := htons(5678);
addr.sin_addr.S_addr := htonl(INADDR_ANY);
bind( MainSock, @addr, sizeof(addr) );
listen( MainSock, 5 );

while (not Terminated) do
begin
FD_ZERO( fd_read );
FD_SET( MainSock, fd_read );
timeout.tv_sec := 0;
timeout.tv_usec := 500;
if select( 0, @fd_read, nil, nil, @timeout ) > 0 then //至少有1个等待Accept的connection
begin
if FD_ISSET( MainSock, fd_read ) then
begin
for i:=0 to fd_read.fd_count-1 do //注意,fd_count <= 64,也就是说select只能同时管理最多64个连接
begin
len := sizeof(addr);
ASock := accept( MainSock, addr, len );
if ASock <> INVALID_SOCKET then
....//为ASock创建一个新的线程,在新的线程中再不停地select
end;
end;
end;
end; //while (not self.Terminated)

shutdown( MainSock, SD_BOTH );
closesocket( MainSock );
end;

http://www.linuxidc.com/Linux/2011-03/33407p5.htm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于非阻塞 I/O 模型的服务器回射程序的代码实现,使用 C 语言和 Linux 系统的 epoll 实现: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <fcntl.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/epoll.h> #define MAX_EVENTS 1024 #define PORT 8888 int main() { // 创建 socket,并设置为非阻塞模式 int listenfd = socket(AF_INET, SOCK_STREAM, 0); if (listenfd < 0) { perror("socket"); exit(EXIT_FAILURE); } fcntl(listenfd, F_SETFL, O_NONBLOCK); // 绑定 IP 地址和端口号 struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(PORT); if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) { perror("bind"); exit(EXIT_FAILURE); } // 监听 socket if (listen(listenfd, SOMAXCONN) < 0) { perror("listen"); exit(EXIT_FAILURE); } // 创建一个事件循环,并注册监听 socket 的读事件 int epfd = epoll_create(1); if (epfd < 0) { perror("epoll_create"); exit(EXIT_FAILURE); } struct epoll_event ev; ev.events = EPOLLIN | EPOLLET; ev.data.fd = listenfd; if (epoll_ctl(epfd, EPOLL_CTL_ADD, listenfd, &ev) < 0) { perror("epoll_ctl"); exit(EXIT_FAILURE); } struct epoll_event events[MAX_EVENTS]; // 在事件循环中,处理监听 socket 的读事件和连接 socket 的读写事件 while (1) { int nfds = epoll_wait(epfd, events, MAX_EVENTS, -1); for (int i = 0; i < nfds; i++) { if (events[i].data.fd == listenfd) { // 有新的连接 while (1) { struct sockaddr_in clientaddr; socklen_t clientaddrlen = sizeof(clientaddr); int connfd = accept(listenfd, (struct sockaddr*)&clientaddr, &clientaddrlen); if (connfd < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { break; } else { perror("accept"); break; } } fcntl(connfd, F_SETFL, O_NONBLOCK); ev.events = EPOLLIN | EPOLLET; ev.data.fd = connfd; if (epoll_ctl(epfd, EPOLL_CTL_ADD, connfd, &ev) < 0) { perror("epoll_ctl"); exit(EXIT_FAILURE); } } } else { // 处理连接的读写事件 int connfd = events[i].data.fd; char buf[1024]; while (1) { int n = read(connfd, buf, sizeof(buf)); if (n < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { break; } else { perror("read"); if (epoll_ctl(epfd, EPOLL_CTL_DEL, connfd, &ev) < 0) { perror("epoll_ctl"); exit(EXIT_FAILURE); } close(connfd); break; } } else if (n == 0) { if (epoll_ctl(epfd, EPOLL_CTL_DEL, connfd, &ev) < 0) { perror("epoll_ctl"); exit(EXIT_FAILURE); } close(connfd); break; } else { write(connfd, buf, n); } } } } } // 关闭 socket close(listenfd); return 0; } ``` 上面的代码实现了一个简单的服务器回射程序,可以同时处理多个连接的读写事件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值