首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > 高性能WEB开发 >

很幽默的讲解六种Socket IO模型(转)解决方法

2012-02-06 
很幽默的讲解六种Socket IO模型(转)本文简单介绍了当前Windows支持的各种Socket I/O模型,如果你发现其中存

很幽默的讲解六种Socket IO模型(转)
本文简单介绍了当前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;

二:WSAAsyncSelect模型

后来,老陈使用了微软公司的新式信箱。这种信箱非常先进,一旦信箱里有新的信件,盖茨就会给老陈打电话:喂,大爷,你有新的信件了!从此,老陈再也不必频繁上下楼检查信箱了,牙也不疼了,你瞅准了,蓝天......不是,微软~~~~~~~~
微软提供的WSAAsyncSelect模型就是这个意思。

WSAAsyncSelect模型是Windows下最简单易用的一种Socket I/O模型。使用这种模型时,Windows会把网络事件以消息的形势通知应用程序。
首先定义一个消息标示常量:
const WM_SOCKET = WM_USER + 55;
再在主Form的private域添加一个处理此消息的函数声明:
private
procedure WMSocket(var Msg: TMessage); message WM_SOCKET;
然后就可以使用WSAAsyncSelect了:
var
addr : TSockAddr;
sock : TSocket;

sock := 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( m_sock, @addr, sizeof(SOCKADDR) );

WSAAsyncSelect( m_sock, Handle, WM_SOCKET, FD_ACCEPT or FD_CLOSE );

listen( m_sock, 5 );
....

应用程序可以对收到WM_SOCKET消息进行分析,判断是哪一个socket产生了网络事件以及事件类型:

procedure TfmMain.WMSocket(var Msg: TMessage);
var
sock : TSocket;
addr : TSockAddrIn;
addrlen : Integer;
buf : Array [0..4095] of Char;
begin
//Msg的WParam是产生了网络事件的socket句柄,LParam则包含了事件类型
case WSAGetSelectEvent( Msg.LParam ) of
FD_ACCEPT :
begin
addrlen := sizeof(addr);
sock := accept( Msg.WParam, addr, addrlen );
if sock <> INVALID_SOCKET then
WSAAsyncSelect( sock, Handle, WM_SOCKET, FD_READ or FD_WRITE or FD_CLOSE );
end;

FD_CLOSE : closesocket( Msg.WParam );
FD_READ : recv( Msg.WParam, buf[0], 4096, 0 );
FD_WRITE : ;
end; 
end;

三:WSAEventSelect模型

后来,微软的信箱非常畅销,购买微软信箱的人以百万计数......以至于盖茨每天24小时给客户打电话,累得腰酸背痛,喝蚁力神都不好使~~~~~~
微软改进了他们的信箱:在客户的家中添加一个附加装置,这个装置会监视客户的信箱,每当新的信件来临,此装置会发出"新信件到达"声,提醒老陈去收信。盖茨终于可以睡觉了。

同样要使用线程:
procedure TListenThread.Execute;
var
hEvent : WSAEvent;
ret : Integer;
ne : TWSANetworkEvents;
sock : TSocket;
adr : TSockAddrIn;
sMsg : String;
Index,
EventTotal : DWORD;
EventArray : Array [0..WSA_MAXIMUM_WAIT_EVENTS-1] of WSAEVENT;
begin
...socket...bind...
hEvent := WSACreateEvent();
WSAEventSelect( ListenSock, hEvent, FD_ACCEPT or FD_CLOSE );
...listen...

while ( not Terminated ) do
begin
Index := WSAWaitForMultipleEvents( EventTotal, @EventArray[0], FALSE, WSA_INFINITE, FALSE );


FillChar( ne, sizeof(ne), 0 );
WSAEnumNetworkEvents( SockArray[Index-WSA_WAIT_EVENT_0], EventArray[Index-WSA_WAIT_EVENT_0], @ne );

if ( ne.lNetworkEvents and FD_ACCEPT ) > 0 then
begin
if ne.iErrorCode[FD_ACCEPT_BIT] <> 0 then
continue;

ret := sizeof(adr);
sock := accept( SockArray[Index-WSA_WAIT_EVENT_0], adr, ret );
if EventTotal > WSA_MAXIMUM_WAIT_EVENTS-1 then//这里WSA_MAXIMUM_WAIT_EVENTS同样是64
begin
closesocket( sock );
continue;
end;

hEvent := WSACreateEvent();
WSAEventSelect( sock, hEvent, FD_READ or FD_WRITE or FD_CLOSE );
SockArray[EventTotal] := sock;
EventArray[EventTotal] := hEvent;
Inc( EventTotal );
end;

if ( ne.lNetworkEvents and FD_READ ) > 0 then
begin
if ne.iErrorCode[FD_READ_BIT] <> 0 then
continue;
FillChar( RecvBuf[0], PACK_SIZE_RECEIVE, 0 );
ret := recv( SockArray[Index-WSA_WAIT_EVENT_0], RecvBuf[0], PACK_SIZE_RECEIVE, 0 );
......
end;
end;
end;




[解决办法]
恩 不错
[解决办法]
加精了,标题你想改成什么样的?
[解决办法]
不错,收下了
[解决办法]
严重支持,努力学习
[解决办法]
这个写得太赞了,哈哈~
[解决办法]
好文 mark!!
[解决办法]
好文
[解决办法]
比喻太恰当,顶。
[解决办法]
好文 mark!!
[解决办法]
饮者留名
[解决办法]
先收,日后再说……
顶一下
[解决办法]

探讨
饮者留名

[解决办法]
探讨
好文 mark!!

[解决办法]
mark
[解决办法]
饮者留名

挺好玩的
[解决办法]
标记一下,以后看
[解决办法]
狂 顶 !!!!!!!!!
[解决办法]
老贴啊
[解决办法]
标记一下,以后看
[解决办法]
狂 顶 !!!!!!!!!
[解决办法]
标记一下,以后看
[解决办法]
mark
[解决办法]
“挺”好
[解决办法]
搜集的挺全的,赞一个

------解决方案--------------------


收藏了 谢谢楼主了
[解决办法]
好帖,顶起
[解决办法]
不得不赞,楼主,一个好人!
[解决办法]
好文 一定要顶一个
[解决办法]
MARK!
[解决办法]
LZ是个好人
[解决办法]

探讨
引用:
好文  mark!!


[解决办法]
mark
[解决办法]
+++++++++++++++++++++++++++++++++++++++++++++++++++
[解决办法]
mark
[解决办法]
收藏,加精收藏
[解决办法]
mark
[解决办法]
马克
[解决办法]
写得很精彩,收藏.
[解决办法]
mark有空看.
[解决办法]
MARK
[解决办法]
确实很强!
[解决办法]
嗯,以前就是看了这个文章理解的
[解决办法]
太牛
[解决办法]

[解决办法]
学习了。
[解决办法]
探讨
引用:
好文 mark!!

[解决办法]
马克~~~~
先看一遍
[解决办法]
学习学习一下了``谢谢LX
[解决办法]
thanks

[解决办法]
MARK~
[解决办法]
mark
[解决办法]
mark
[解决办法]
写得很精彩,收藏.
[解决办法]
眼泪哗哗的~
[解决办法]
m
[解决办法]
好贴,但我没有看完
[解决办法]
mark`
[解决办法]
收藏
------解决方案--------------------


收藏
[解决办法]
LZ 写的好!
   支持!
[解决办法]
收藏
[解决办法]
写太好了
[解决办法]
MARK

[解决办法]
写的挺好的
只是我看的有点晕
没完全消化

下次有时间在好好琢磨
[解决办法]
很好很强大 

学习了很多

不错
[解决办法]
加精收藏
[解决办法]
学习呢 !谢谢
[解决办法]
mark
[解决办法]
mark,好文,谢谢楼主了
[解决办法]
发现是c 了以后就没看下去了。。。
[解决办法]
好文 寓教于乐~
[解决办法]
通俗易懂,好!
[解决办法]
好,收藏
[解决办法]
up
[解决办法]
牛牛,收藏了
[解决办法]
very good
[解决办法]
mark,慢慢看
[解决办法]
给大家推荐个好用的文件上传组件,主要功能:
压缩上传、批量上传、断点续传等

如有需求和上面的不一样的,可以按照你的要求定制。

联系方式:
QQ:894737428,加入时请注明:需要上传组件。
mail:txjw4650@sina.com
[解决办法]
收藏起来。
[解决办法]
好文 mark!!
[解决办法]
mark
[解决办法]
这样的贴子不顶,对不起兄弟您啊!
[解决办法]
我来学习来了
[解决办法]

[解决办法]
讲了一堆屁话,根本没有把
select模型 
WSAAsyncSelect模型 
WSAEventSelect模型 
Overlapped I/O 事件通知模型 
Overlapped I/O 完成例程模型 
IOCP模型 

的特点讲出来.误人子弟!!!

[解决办法]
我的。。。。。。。。。。。。。。。。。。。
[解决办法]
学习了

热点排行