CAsyncSocket

本词条缺少名片图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧!

它是一个异步非阻塞Socket封装类,CAsyncSocket::Create()有一个参数指明了你想要处理哪些Socket事件,你关心的事件被指定以后,这个Socket默认就被用作了异步方式。CAsyncSocket的Create()函数,除了创建了一个SOCKET以外,还创建了个CSocketWnd窗口对象,并使用WSAAsyncSelect()将这个SOCKET与该窗口对象关联,以让该窗口对象处理来自Socket的事件(消息),然而CSocketWnd收到Socket事件之后,只是简单地回调CAsyncSocket::OnReceive()等虚函数。所以CAsyncSocket的派生类,只需要在这些虚函数里添加发送和接收的代码。

中文名

好    处

极大方便

实    质

异步非阻塞Socket封装类

发送和接收

虚函数

目录


1大致的代码为


2特别注意


3CAsyncsocket好处

1大致的代码为编辑

bool CAsyncSocket::Create( long lEvent ) //参数lEvent是指定你所关心的Socket事件

{

m_hSocket = socket( PF_INET, SOCK_STREAM, 0 ); //创建Socket对象

CSocketWnd* pSockWnd = new CSocketWnd; //创建响应事件的窗口,实际的这个窗口在AfxSockInit()调用时就被创建了。

pSockWnd->Create(...);

WSAAsyncSelect( m_hSocket, pSockWnd->m_hWnd, WM_SOCKET_NOTIFY, lEvent ); //Socket 事件和窗口关联

}

static void PASCAL CAsyncSocket::DoCallBack(WPARAM wParam, LPARAM lParam)

{

CAsyncSocket Socket;

Socket.Attach( (SOCKET)wParam ); //wParam 就是触发这个事件的Socket的句柄

int nErrorCode = WSAGETSELECTERROR(lParam); //lParam 是错误码与事件码的合成

switch (WSAGETSELECTEVENT(lParam))

{

case FD_READ:

pSocket->OnReceive(nErrorCode);

break;

case FD_WRITE:

pSocket->OnSend(nErrorCode);

break;

case FD_OOB:

pSocket->OnOutOfBandData(nErrorCode);

break;

case FD_ACCEPT:

pSocket->OnAccept(nErrorCode);

break;

case FD_CONNECT:

pSocket->OnConnect(nErrorCode);

break;

case FD_CLOSE:

pSocket->OnClose(nErrorCode);

break;

}

}

CSocketWnd类大致为:

BEGIN_MESSAGE_MAP(CSocketWnd, CWnd)

ON_MESSAGE(WM_SOCKET_NOTIFY, OnSocketNotify)

END_MESSAGE_MAP()

LRESULT CSocketWnd::OnSocketNotify(WPARAM wParam, LPARAM lParam)

{

CAsyncSocket::DoCallBack( wParam, lParam ); //收到Socket事件消息,回调CAsyncSocket的DoCallBack()函数

return 0L;

}

然而,最不容易被初学Socket编程的人理解的,也是本文最要提醒的一点是,客户方在使用CAsyncSocket::Connect()时,往往返回一个WSAEWOULDBLOCK的错误(其它的某些函数调用也如此),实际上这不应该算作一个错误,它是Socket提醒我们,由于你使用了非阻塞Socket方式,所以(连接)操作需要时间,不能瞬间建立。既然如此,我们可以等待呀,等它连接成功为止,于是许多程序员就在调用Connect()之后,Sleep(0),然后不停地用WSAGetLastError()或者CAsyncSocket::GetLastError()查看Socket返回的错误,直到返回成功为止。这是一种错误的做法,断言,你不能达到预期目的。事实上,我们可以在Connect()调用之后等待CAsyncSocket::OnConnect()事件被触发,CAsyncSocket::OnConnect()是要表明Socket要么连接成功了,要么连接彻底失败了。至此,我们在CAsyncSocket::OnConnect()被调用之后就知道是否Socket连接成功了,还是失败了。

类似的,Send()如果返回WSAEWOULDBLOCK错误,我们在OnSend()处等待,Receive()如果返回WSAEWOULDBLOCK错误,我们在OnReceive()处等待,以此类推。

2特别注意编辑

还有一点,也许是个难点,那就是在客户方调用Connect()连接服务方,那么服务方如何Accept(),以建立连接的问题。简单的做法就是在监听的Socket收到OnAccept()时,用一个新的CAsyncSocket对象去建立连接,例如:

void CMySocket::OnAccept( int ErrCode )

{

CMySocket* pSocket = new CMySocket;

Accept( *pSocket );

}

于是,上面的pSocket和客户方建立了连接,以后的通信就是这个pSocket对象去和客户方进行,而监听的Socket仍然继续在监听,一旦又有一个客户方要连接服务方,则上面的OnAccept()又会被调用一次。当然pSocket是和客户方通信的服务方,它不会触发OnAccept()事件,因为它不是监听Socket。

3CAsyncsocket好处编辑

CAsyncSocket类为我们使用Socket提供了极大方便。建立Socket的WSAStartup过程和bind过程被简化成为Create过程,IP地址类型转换主机名和IP地址转换的过程中许多复杂的变量类型都被简化成字符串和整数操作,特别是CAsyncSocket类的异步特点,完全可以替代繁琐的线程操作。MFC提供了大量的类库,我们若能灵活的使用他们,便会大大提高编程的效率。

时间: 2024-11-13 03:44:35

CAsyncSocket的相关文章

CAsyncSocket只传输了一部分数据(UDP),后面是乱码

void CCAsyncSocketDlg::OnBnClickedBtnSend() { UpdateData(TRUE); TCHAR ipstr[INET_ADDRSTRLEN]; DWORD dwRemoteIp = htonl(m_dwRemoteIp); InetNtop(AF_INET, &dwRemoteIp, ipstr, sizeof ipstr)); int nWrite = m_sockLocal.SendToEx(m_strSend.GetBuffer(), m_str

CAsyncSocket,CSocket内幕及其用法

由于需要写个wince通信程序,首先想到的是c#,但觉得c#写那个太简单了点于是选择了稍微难点的mfc,但是没想到mfc中的csocket在wince中竟然会报异常,悲催,经查证,原来是indows CE Embeded不支持异步传输模式(例如WSAAsyncSelect函数),而mfc中的套接字都是基于异步实现的,因此,很无奈,只能使用原始的winsock了,具体如下 Socket API,CAsyncSocket,CSocket内幕及其用法jmcooler(原作)    关键字     So

CAsyncSocket网络编程(MFC)

随着计算机网络化的深入,计算机网络编程在程序设计的过程中变得日益重要.由于C++语言对底层操作的优越性,许多文章都曾经介绍过用VC++进行Socket编程的方法.但由于都是直接利用动态连接库wsock32.dll进行操作,实现比较繁琐.其实,VC++的MFC类库中提供了CAsyncSocket这样一个套接字类,用他来实现Socket编程,是非常方便的. ---- 本文将用一个Echo例程来介绍CAsyncSocket类的用法. ---- 一. 客户端 ---- 1. 创建一个Dialog Bas

[转载]CAsyncSocket及CSocket注解

MFC疑难注解:CAsyncSocket及CSocket MFC对SOCKET编程的支持其实是很充分的,然而其文档是语焉不详的.以至于大多数用VC编写的功能稍复杂的网络程序,还是使用API的.故CAsyncSocket及CSocket事实上成为疑难,群众多敬而远之.余好事者也,不忍资源浪费,特为之注解. 一.CAsyncSocket与CSocket的区别 前者是异步通信,后者是同步通信:前者是非阻塞模式,后者是阻塞模式.另外,异步非阻塞模式有时也被称为长连接,同步阻塞模式则被称为短连接.为了更明

MFC CSocket和CAsyncSocket的连接

MFC CSocket和CAsyncSocket的连接 flyfish 2015-1-31 CSocket的Connect是阻塞的. 所以代码类似 if(!Connect()) { } 判断成功还是失败 CAsyncSocket的Connect是非阻塞的 当调用CAsyncSocket::Connect连接一个服务器 虽然CAsyncSocket::Connect函数返回值是BOOL类型, 但代码不是 if(!Connect()) { } 当连接操作完成,完成(complete)!=成功(suc

MFC中CAsyncSocket及其派生类对象跨线程使用方法

存在的现象 在MFC中用多线程方法开发WinSocket通讯程序时,如果你的的是API方式,自然没有以下说的问题.但如果当你使用CAsyncSocket及其派生类(CSocket或是你自己的写的)来开发的话,会发现在不同线程中使用CAsyncSocket及其派生类对象时,会出现程序崩溃.这里所说的跨线程,是指该对象在一个线程中调用Create/Close/Attach/Detach函数,然后在另外一个线程中调用其他成员函数如Receive/ReceiveFrom/Send/SendTo等.下面是

socket API CSocket CAsyncSocket 用法及区别

要进行网络编程就要和Socket打交道,Socket有同步阻塞方式和异步非阻塞方式两种使用,事实上同步和异步在我们编程的生涯中可能遇到了很多,而Socket也没什么特别.虽然同步好用,不费劲,但不能满足一些应用场合,其效率也很低.    或许初涉编程的人不能理解"同步(或阻塞)"和"异步(或非阻塞)",其实简单两句话就能讲清楚,同步和异步往往都是针对一个函数来说的,"同步"就是函数直到其要执行的功能全部完成时才返回,而"异步"

静态MFC CSocket CAsyncSocket map_pp.cpp错误

静态MFC,在线程中使用SOCKET,发生错误: Debug Assertion Failed!Program:...File:f:\rtm\vctools\vc7libs\ship\atlmfc\src\mfc\map_pp.cppLine:179 这是MFC的一个BUG,在6.0中就发现,可惜微软到VS2013还是没有修改,估计这个东西微软也要淘汰了,懒得改了,下面是MSDN的解决方法: When using MFC sockets in secondary threads in a sta

将socket程序从linux移植到windows上

今天突然想试下纯socket编程在两个系统上代码重合量有多大,只要不使用VC自定义的宏(比如SOCKET.SOCKADDR等等)感觉代码重合量挺大的. 比如最简单的TCP客户端和服务端对话,在VC中用int取代SOCKET宏,用struct sockaddr_in取代SOCKADDR_IN宏. 然后区别就仅仅是头文件和windows额外加载/关闭套接字库的代码了. // Unix/Linux#include <sys/socket.h> #include <netinet/in.h>