首页 > 代码库 > MFC CSocket和CAsyncSocket的连接

MFC CSocket和CAsyncSocket的连接

MFC CSocket和CAsyncSocket的连接


flyfish 2015-1-31



CSocket的Connect是阻塞的。
所以代码类似
if(!Connect())
{
}
判断成功还是失败


CAsyncSocket的Connect是非阻塞的
当调用CAsyncSocket::Connect连接一个服务器
虽然CAsyncSocket::Connect函数返回值是BOOL类型,
但代码不是
if(!Connect())
{
}
当连接操作完成,完成(complete)!=成功(successful ),应用程序将接收到OnConnect消息
所以需要重载OnConnect ,要在void 派生类::OnConnect(int nErrorCode)判断参数nErrorCode判断成功还是失败。


如果该类是派生于CSocket,也想要在OnConnect里判断
看源码


_AFXSOCK_INLINE BOOL CAsyncSocket::Connect(const SOCKADDR* lpSockAddr, int nSockAddrLen)
	{ return ConnectHelper(lpSockAddr, nSockAddrLen); }

BOOL CAsyncSocket::ConnectHelper(const SOCKADDR* lpSockAddr, int nSockAddrLen)
{
	return connect(m_hSocket, lpSockAddr, nSockAddrLen) != SOCKET_ERROR;
}

BOOL CAsyncSocket::Connect(LPCTSTR lpszHostAddress, UINT nHostPort)
{
	USES_CONVERSION_EX;


	ASSERT(lpszHostAddress != NULL);


	if (lpszHostAddress == NULL)
	{
		WSASetLastError (WSAEINVAL);
		return FALSE;
	}


	SOCKADDR_IN sockAddr;
	memset(&sockAddr,0,sizeof(sockAddr));


	LPSTR lpszAscii = T2A_EX((LPTSTR)lpszHostAddress, _ATL_SAFE_ALLOCA_DEF_THRESHOLD);
	if (lpszAscii == NULL)
	{
		WSASetLastError(ERROR_NOT_ENOUGH_MEMORY);
		return FALSE;
	}


	sockAddr.sin_family = AF_INET;
	sockAddr.sin_addr.s_addr = inet_addr(lpszAscii);


	if (sockAddr.sin_addr.s_addr == INADDR_NONE)
	{
		LPHOSTENT lphost;
		lphost = gethostbyname(lpszAscii);
		if (lphost != NULL)
			sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
		else
		{
			WSASetLastError(WSAEINVAL);
			return FALSE;
		}
	}


	sockAddr.sin_port = htons((u_short)nHostPort);


	return Connect((SOCKADDR*)&sockAddr, sizeof(sockAddr));
}

BOOL CSocket::ConnectHelper(const SOCKADDR* lpSockAddr, int nSockAddrLen)
{
	if (m_pbBlocking != NULL)
	{
		WSASetLastError(WSAEINPROGRESS);
		return  FALSE;
	}


	m_nConnectError = -1;


	if (!CAsyncSocket::ConnectHelper(lpSockAddr, nSockAddrLen))
	{
		if (GetLastError() == WSAEWOULDBLOCK)
		{
			while (PumpMessages(FD_CONNECT))
			{
				if (m_nConnectError != -1)
				{
					WSASetLastError(m_nConnectError);
					return (m_nConnectError == 0);
				}
			}
		}
		return FALSE;
	}
	return TRUE;
}





如果是CAsyncSocket::Connect
调用的是CAsyncSocket::Connect -》CAsyncSocket::ConnectHelper 


如果是CSocket Connect时
CAsyncSocket::Connect -》CSocket::ConnectHelper 在这里产生了阻塞


阻塞与非阻塞的区别就在ConnectHelper 


如果想要CSocket的派生类更改为CAsyncSocket的连接方式

只要在派生类重载ConnectHelper 和 OnConnect


声明
virtual BOOL ConnectHelper(const SOCKADDR* lpSockAddr,int nSockAddrLen);
virtual void OnConnect(int nErrorCode);



实现
BOOL 派生类::ConnectHelper(const SOCKADDR* lpSockAddr,int nSockAddrLen)
{
	return connect(m_hSocket, lpSockAddr, nSockAddrLen) != SOCKET_ERROR;
}


void 派生类::OnConnect(int nErrorCode)
{
}







MFC CSocket和CAsyncSocket的连接