基于消息的异步套接字

基于消息的异步套接字

Windows套接字在两种模式下执行I/O操作,阻塞模式和非阻塞模式。在阻塞模式下,在I/O操作完成前,执行操作的Winsock函数会一直等待下去,不会立即返回(也就不会将控制权交还给程序),而在非阻塞模式下,Winsock函数无论如何都会立即返回,在该函数执行的操作完成之后,系统会采用某种方式将操作结果通知给调用线程,后者根据通知信息可以判断该操作是正常完成,还是出现错误了。
因为在很多情况下,阻塞方式会影响应用程序的性能,所以有时需要采用非阻塞方式实现网络应用程序。Windows Sockets为了支持Windows消息驱动机制,使应用程序开发者能够方便地处理网络通信,它对网络事件采用了基于消息的异步存取策略。Windows Sockets的异步选择函数WSAAsyncSelect提供了消息机制的网络事件选择,当使用它登记的网络事件发生时,Windows应用程序相应的窗口函数将收到一个消息,消息中指示了发生的网络事件,以及该事件相关的一些信息。

相关函数

WSASocket();--创建套接字
WSAAsyncSelect();--为指定的套接字请求基于Windows消息的网络事件通知,并自动将该套接字设置为非阻塞模式
WSASendTo();--发送数据报类型的数据
WSARecvFrom();--接收数据报类型的数据

例子(网络聊天室--部分代码)

BOOL CChatDlg::InitSocket(void)
{
m_socket=WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,0);
if(m_socket==INVALID_SOCKET)
{
AfxMessageBox("创建套接字失败!");
return FALSE;
}
SOCKADDR_IN addrSock;
ZeroMemory(&addrSock,sizeof(SOCKADDR_IN));
addrSock.sin_family=AF_INET;
addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSock.sin_port=htons(8000);
int flag=1;
int len =sizeof(int);
if(setsockopt(m_socket,SOL_SOCKET,SO_REUSEADDR,(const char*)&flag,len)==SOCKET_ERROR)
{
AfxMessageBox("设置套接字选项失败!");
return FALSE;
}
if(bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR))==SOCKET_ERROR)
{
AfxMessageBox("绑定套接字失败!");
return FALSE;
}
if(WSAAsyncSelect(m_socket,m_hWnd,UM_SOCK,FD_READ)==SOCKET_ERROR)
{
AfxMessageBox("注册网络读取事件失败!");
return FALSE;
}
return TRUE;
}

//自定义消息处理函数
LRESULT CChatDlg::OnSock(WPARAM wParam,LPARAM lParam)
{
switch(LOWORD(lParam))
{
case FD_READ:
WSABUF wsaBuf;
wsaBuf.buf=new char[200];
wsaBuf.len=200;
DWORD dwRead;
DWORD dwFlag=0;
SOCKADDR_IN addrFrom;
int len =sizeof(SOCKADDR_IN);
ZeroMemory(&addrFrom,sizeof(SOCKADDR_IN));
if(WSARecvFrom(m_socket,&wsaBuf,1,&dwRead,&dwFlag,(SOCKADDR*)&addrFrom,&len,NULL,NULL)==SOCKET_ERROR)
{
AfxMessageBox("接收数据失败!");
delete[] wsaBuf.buf;
return FALSE;
}
CString str,strTemp;
str.Format("%s说:%s",inet_ntoa(addrFrom.sin_addr),wsaBuf.buf);
str+="\r\n";
GetDlgItemText(IDC_EDIT_RECV,strTemp);
str+=strTemp;
SetDlgItemText(IDC_EDIT_RECV,str);
delete[] wsaBuf.buf;
break;
}
return TRUE;
}

void CChatDlg::OnBnClickedButtonSend()
{
// TODO: 在此添加控件通知处理程序代码
DWORD dwIP;
CString strSend;
WSABUF wsaBuf;
DWORD dwSend;
int len;
SOCKADDR_IN addrTo;


CString strHostName;
HOSTENT*pHost;
if(GetDlgItemText(IDC_EDIT_HOSTNAME,strHostName),strHostName=="")
{
((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);
addrTo.sin_addr.S_un.S_addr=htonl(dwIP);
}
else
{
pHost=gethostbyname(strHostName);
addrTo.sin_addr.S_un.S_addr=*(DWORD*)pHost->h_addr_list[0];
}
addrTo.sin_port=htons(8000);
addrTo.sin_family=AF_INET;


GetDlgItemText(IDC_EDIT_SEND,strSend);
len=strSend.GetLength();
wsaBuf.buf=strSend.GetBuffer();
wsaBuf.len=len+1;


if(WSASendTo(m_socket,&wsaBuf,1,&dwSend,0,(SOCKADDR*)&addrTo,sizeof(SOCKADDR),NULL,NULL)==SOCKET_ERROR)
{
AfxMessageBox("发送数据失败!");
return;
}
SetDlgItemText(IDC_EDIT_SEND,"");
}



在编写网络应用程序时,采用异步选择机制可以提高网络应用程序的性能,如果再配合多线程技术,将大大提高所编写的网络应用程序的性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值