网络编程笔记WSAAsyncSelect模型herocao的博客.docx

上传人:b****8 文档编号:9710874 上传时间:2023-05-20 格式:DOCX 页数:7 大小:16.94KB
下载 相关 举报
网络编程笔记WSAAsyncSelect模型herocao的博客.docx_第1页
第1页 / 共7页
网络编程笔记WSAAsyncSelect模型herocao的博客.docx_第2页
第2页 / 共7页
网络编程笔记WSAAsyncSelect模型herocao的博客.docx_第3页
第3页 / 共7页
网络编程笔记WSAAsyncSelect模型herocao的博客.docx_第4页
第4页 / 共7页
网络编程笔记WSAAsyncSelect模型herocao的博客.docx_第5页
第5页 / 共7页
网络编程笔记WSAAsyncSelect模型herocao的博客.docx_第6页
第6页 / 共7页
网络编程笔记WSAAsyncSelect模型herocao的博客.docx_第7页
第7页 / 共7页
亲,该文档总共7页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

网络编程笔记WSAAsyncSelect模型herocao的博客.docx

《网络编程笔记WSAAsyncSelect模型herocao的博客.docx》由会员分享,可在线阅读,更多相关《网络编程笔记WSAAsyncSelect模型herocao的博客.docx(7页珍藏版)》请在冰点文库上搜索。

网络编程笔记WSAAsyncSelect模型herocao的博客.docx

网络编程笔记WSAAsyncSelect模型herocao的博客

网络编程笔记----WSAAsyncSelect模型--herocao的博客

Winsock提供了一个有用的异步I/O模型。

利用这个模型,应用程序可在一个套接字上,

接收以Windows消息为基础的网络事件通知。

具体的做法是在建好一个套接字后,调用

WSAAsyncSelect函数。

此模型提供了读写数据能力的异步通知,但不提供异步数据传送。

异步数据传送有“重叠及完成端口模型提供”。

消息通知

要想使用WSAAsyncSelect模型,在应用程序中,首先必须用CreateWindow函数创建一个窗口,再为该窗口提供一个窗口例程支持函数(Winproc)。

亦可使用一个对话框,为其提供一个对话例程,而非窗口例程,因为对话框本质也是“窗口”。

intWSAAsyncSelect(

 

SOCKETs,//要进行操作的SOCKET

 

HWNDhWnd,//要绑写的窗口句柄(当事件发生后要接收消息的窗口)

 

unsignedintwMsg,//网络事件发生时的的消息响应

 

longlEvent//感兴趣的网络事件,请查阅MSDN

 

);

使用方法可分为:

(1)初始化套接字相关信息:

(2)开始启动一个事件通知。

WSAAsyncSelect(Sock,hWnd,自定义消息,网络事件)

(3)响应窗口的自定义消息处理函数, 其中lparam的高位字包含了可能出现的错误

代码,低字节表示发生的网络事件。

wParam表示发生网络事件的套接字。

WSAGETSELECTERROR(lParam);//查看是否出现错误,获取低字节位

WSAGETSELECTEVENT(lParam);//查看发生了什么事件,获取高字节位

事件种类请查看MSDN,可用WSAGetLastError()来获取错误息。

注意:

多个事件必须一次注册完成,一旦在某个套接字上启用了事件通知,注册过的事件将一直有效,除非明确调用closesocket命令,或针对这个套接字再调用WSAAsyncSelect更改注册过的网络事件。

优点:

可在系统开销不大的情况下同时处理许多连接。

缺点:

即使用不需要窗口(如服务器,控制台)它也不得不额外使用一个窗口。

同时如果处理成千上万套接字的所有事件,性能可想而知。

MFC的CSocket所使用的正是这种事件通知模型

今天看了一下,消息通知的几个类型。

用的比较多的可能就是FD_SEND,FD_WRITE,在网上查了一下资料,总结如下:

【FD_WRITE事件】

(1)呼叫WSAAsyncSelect()来设定FD_WRITE事件时,Socket已经可以传送资料(TCPscoket已经和对方连接成功了,或UDPsocket已建立完成),且目前outputbuffer仍有空间可写入资料。

(2)呼叫WSAAsyncSelect()来设定FD_WRITE事件时,Socket尚不能传送资料,不过一旦Socket与对方连接成功,马上就会收到FD_WRITE的通知。

(3)呼叫send()或sendto()传送资料时,系统告知错误,且错误码为10035WSAEWOULDBLOCK(呼叫WSAGetLastError()得知这项错误),这时表示outputbuffer已经满了,无法再写入任何资料(此时即令呼叫再多次的send()也都一定失败);一旦系统将部份资料成功送抵对方,空出outputbuffer后,便会送一个FD_WRITE给使用者,告知可继续传送资料了。

换句话说,读者在呼叫send()传送资料时,只要不是返回错误10035的话,便可一直继续呼叫send()来传送资料;一旦send()回返错误10035,那麽便不要再呼叫send()传送资料,而须等收到FD_WRITE后,再继续传送资料。

如果只是发送很少的数据,可能只出现第二种情况,所以在发送少量数据的时候,不要使用FD_WRITE机制。

【FD_READ事件】

(1)呼叫WSAAsyncSelect函式来对此Socket设定FD_READ事件时,inputbuffer中已有资料。

(2)原先系统的inputbuffer是空的,当系统再收到资料时,会通知我们。

(3)使用者呼叫recv或recvfrom函式,从inputbuffer读取资料,但是并没有一次将资料读光,此时会再驱动一个FD_READ事件,表示仍有资料在inputbuffer中。

读者必须注意:

如果我们收到FD_READ事件通知的讯息,但是我们故意不呼叫recv或recvfrom来读取资料的话,尔後系统又收到资料时,并不会再次通知我们,一定要等我们呼叫了recv或recvfrom後,才有可能再收到FD_READ的事件通知。

 

下面是一个利用WSAAsyncSelect的小程序:

WORDwVersionRequested;

WSADATAwsaData;

interr;

wVersionRequested=MAKEWORD(2,2);

err=WSAStartup(wVersionRequested,&wsaData);

if(err!

=0)

{

return;

}

if(LOBYTE(wsaData.wVersion)!

=2||

HIBYTE(wsaData.wVersion)!

=2)

{

WSACleanup();

return;

spanlang="EN-US"style="LINE-HEIGHT:

150%;FONT-FAMILY:

宋体;mso-bidi-font-size:

10.5pt;mso-font-kerning:

0pt;mso-bidi-font-family:

AdobeSongStd-Light-Acro">}

 

charhostname[256];

gethostname(hostname,sizeof(hostname));//这一代码是为

HOSTENT*hos=gethostbyname(hostname);//了实现自动获取安

CStringCS=inet_ntoa(*(structin_addr*)hos->h_addr_list[0]);//装程序的主机代码

SOCKETserverSocket;

serverSocket=socket(AF_INET,SOCK_STREAM,0);

SOCKADDR_INaddr;

addr.sin_family=AF_INET;

addr.sin_port=htons(6000);

addr.sin_addr.S_un.S_addr=inet_addr(CS);

bind(serverSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR));

//注册网络事件

if(SOCKET_ERROR==WSAAsyncSelect(serverSocket,m_hWnd,WM_NETMESSAGE,FD_ACCEPT|FD_CLOSE))

{

MessageBox("注册事件出错!

");

closesocket(serverSocket);

WSACleanup();

return;

}

listen(serverSocket,5);

}

voidCAsyselectsrvDlg:

:

Onrecvmessage(WPARAMwParam,LPARAMlParam)

{

if(WSAGETSELECTERROR(lParam))

{

AfxMessageBox("接受消息错误");

closesocket(wParam);

return;

}

switch(WSAGETSELECTEVENT(lParam))

{

caseFD_ACCEPT:

 

acceptclient(wParam,m_hWnd);

break;

caseFD_WRITE:

MessageBox("write");

break;

caseFD_READ:

MessageBox("read");

break;

caseFD_CLOSE:

closesocket(wParam);

break;

default:

break;

}

return;

}

voidacceptclient(SOCKETsock,HWNDhwnd)

{

SOCKETacceptclient;

SOCKADDR_INclientaddr;

intlen=sizeof(SOCKADDR_IN);

acceptclient=accept(sock,(structsockaddr*)&clientaddr,&len);

if(SOCKET_ERROR==WSAAsyncSelect(acceptclient,hwnd,WM_NETMESSAGE,FD_READ|FD_WRITE|FD_CLOSE))

{

AfxMessageBox("注册消息出错!

");

closesocket(sock);

closesocket(acceptclient);

WSACleanup();

return;

}

}

这段程序可以正常运行,前面定义全局函数:

voidacceptclient(SOCKETsock,HWNDhwnd);

今晚就写到这里了。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 法律文书

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2