异步套接字编程:

1.    异步套接字编程:

//①自定义消息

#define UM_SOCK  WM_USER+1

         //②做一个消息响应函数的申明

afx_msg voidOnSock(WPARAM, LPARAM);

 

//在析构函数当中关闭套接字,释放与套接字相关的资源

CChatDlg::~CChatDlg()

{

if(m_socket)

           closesocket(m_socket);

}

 

BOOL CChatDlg::OnInitDialog()

{

InitSocket();

return TRUE; // return TRUE  unless you set thefocus to a control

}

 

BOOLCChatDlg::InitSocket()

{

m_socket = WSASocket(AF_INET, SOCK_DGRAM, 0,NULL, 0, 0);

if(INVALID_SOCKET == m_socket)

{

           MessageBox("创建套接字失败!");

           return FALSE;

}

//定义一个地址结构体的变量

SOCKADDR_IN addrSock;

addrSock.sin_addr.S_un.S_addr =htonl(INADDR_ANY);

addrSock.sin_family = AF_INET;

addrSock.sin_port = htons(6000);

if(SOCKET_ERROR == bind(m_socket, (SOCKADDR*)&addrSock,sizeof(SOCKADDR) ))

{

           MessageBox("绑定失败!");

           return FALSE;

}

 

//请求一个基于消息的windows网络事件通知

if(SOCKET_ERROR == WSAAsyncSelect(m_socket,m_hWnd, UM_SOCK, FD_READ))

{

           MessageBox("注册网络读取事件失败!");

           return FALSE;

}

return TRUE;

}

 

//③消息响应函数

voidCChatDlg::OnSock(WPARAM wParam, LPARAM lParam)

{

//首先要去判断一下是不是网络读取事件发生了,然后再去调用接收

//函数去接收数据。

 

switch(LOWORD(lParam))

{

case FD_READ:

           //定义一个WSABUF结构体的变量

           WSABUF wsabuf;

           //分配空间

           wsabuf.buf = new char[200];

           wsabuf.len = 200;

           DWORD dwRead;

         DWORDdwFlag = 0;

           //定义一个地址结构体的变量,接收到来的地址信息

           SOCKADDR_IN addrFrom;

           //用地址结构体的长度做一个初始化

           int len = sizeof(SOCKADDR);

           CString str;

           CString strTemp;

           HOSTENT *pHost;

           if(SOCKET_ERROR ==WSARecvFrom(m_socket, &wsabuf, 1, &dwRead, &dwFlag,

                    (SOCKADDR*)&addrFrom,&len, NULL, NULL))

           {

                    MessageBox("接收数据失败!");

                    return;

           }

           //从地址结构体的变量当中取出一个以网络字节序表示的ulong类型

           //addrFrom.sin_addr.S_un.S_addr这是一个ulong类型,而我们需要char*

           //首先取地址(&),就得到了ulong的指针,加上(char*)就可以得到字符指针类型

           pHost = gethostbyaddr((char*)&addrFrom.sin_addr.S_un.S_addr,4, AF_INET );

 

           //将接收到的数据做一个格式化,取出发送端的IP地址

//      str.Format("%s说: %s",inet_ntoa(addrFrom.sin_addr),wsabuf.buf);

           //通过pHost取出主机的名字

           str.Format("%s说 :%s",pHost->h_name ,wsabuf.buf);

 

           str += "\r\n";

           GetDlgItemText(IDC_EDIT_RECV,strTemp);

           str +=strTemp;

           SetDlgItemText(IDC_EDIT_RECV,str);

           break;

}

}

 

//发送端

voidCChatDlg::OnBtnSend()

{

//接收IP地址

DWORD dwIP;

CString strSend;

//定义一个WSABUF结构体的变量

WSABUF wsabuf;

//接收实际发送的字节数

DWORD dwSend;

//主要时用来保存CString对象当中字符的数目

int len;

CString strHostName;

SOCKADDR_IN addrTo;

HOSTENT* pHost;

if(GetDlgItemText(IDC_EDIT_HOSTNAME,strHostName), strHostName == "")

{

           //调用GetAddress得到IP地址

           ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);

   addrTo.sin_addr.S_un.S_addr = htonl(dwIP);

}

else

{

           pHost = gethostbyname(strHostName);

           //如何将一个字符指针转换ulong类型呢?

           //pHost->h_addr_list[0]可以先将得到的IP地址数据取出来

           //现在取出的就是一个字符的指针,而这个字符指针中存放的就是以网络字节序表示的地址

           //如何将这个指针转换为一个ulong类型呢?

           //既然它是一个字符指针,我们先将它转化为一个DWORD类型指针,指针之间可以相互转换,

           //只要它的内存是兼容的就行了。再用一个*取出这个指针所指向的ulong类型的数据

           //ulong类型占四个字节。

           //①(DWORD*)pHost->h_addr_list[0]先将它转化为DWORD指针,

           //②然后再取值:*((DWORD*)pHost->h_addr_list[0])

           //对于DWORD指针取值的话,取出四个字节,这四个字节正好是网络字节序表示的ulong类型的地址

           addrTo.sin_addr.S_un.S_addr =*((DWORD*)pHost->h_addr_list[0]);

}

 

 

addrTo.sin_family = AF_INET;

addrTo.sin_port = htons(6000);

 

//去获取我们要发送的字节数

GetDlgItemText(IDC_EDIT_SEND, strSend);

 

//这里不能直接将CString对象赋给它

len = strSend.GetLength();

//GetBuffer可以将一个CString对象转换为一个char* 返回

wsabuf.buf = strSend.GetBuffer(len);

//加一个字节,主要是传递一个\0,让接收端接收的字符有一个/0结尾

wsabuf.len = len + 1;

 

SetDlgItemText(IDC_EDIT_SEND, "");

//发送数据

if(SOCKET_ERROR == WSASendTo(m_socket,&wsabuf, 1, &dwSend, 0,

           (SOCKADDR*)&addrTo,sizeof(SOCKADDR), NULL, NULL))

    {

           MessageBox("发送数据失败!");

           return;

}

}

 

//总结:

//在windows平台下,它的程序的运行都是基于消息的,所以选择异步选择机制

//可以提高编写的网络应用程序的效率。

//在windows平台下,我们要想编写一个高性能的网络应用程序,除了对协议本身

//有所了解以外,还需要了解程序在windows平台下工作的原理。

//我们在编写网络应用程序的时候,因为网络的状况瞬息万变,所以我们在调用

//函数的时候,总是应该对这个函数的返回值做一个判断,如果出错了应该怎么样

//去处理。

//在编写网络应用程序的时候,一定要仔细,要多做实验,基于我们所运行的平台

//的特点,相应的去调整网络应用程序实现的细节,这样才能编写出高性能的网络应用程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值