📄 te_socket.cpp
字号:
}
// 注册FD_CONNECT事件
if( WSAEventSelect(hSocket, (WSAEVENT) hConnectEvent, FD_CONNECT) == SOCKET_ERROR)
{
CloseHandle(hConnectEvent);
TE_SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
int iConnectResult = WSAConnect(hSocket, pSocketAddress, iNameLen, NULL, NULL, NULL, NULL);
int iConnectError = WSAGetLastError();
if ((iConnectResult == SOCKET_ERROR) && (iConnectError == WSAEWOULDBLOCK))
{
DWORD dwWaitResult = WSAWaitForMultipleEvents(1, &hConnectEvent, TRUE,dwTimeout, TRUE);
if (dwWaitResult != WSA_WAIT_EVENT_0)
{
TE_SetLastError( WSAGetLastError() );
iConnectResult = SOCKET_ERROR;
}
else
{
//////////////////////////////////////////////////////////////
/// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该
/// 进一步检查网络是否发生错误
///////////////////////////////////////////////////////////////
WSANETWORKEVENTS NetEvent;
if(WSAEnumNetworkEvents(hSocket,(WSAEVENT)hConnectEvent,&NetEvent) == SOCKET_ERROR)
{
TE_SetLastError( WSAGetLastError() );
iConnectResult = SOCKET_ERROR;
}
else if(NetEvent.iErrorCode[FD_CONNECT_BIT] !=0 ) // 发生错误
{
TE_SetLastError( NetEvent.iErrorCode[FD_CONNECT_BIT] );
iConnectResult = SOCKET_ERROR;
}
else
iConnectResult = SOCKET_SUCCESS;
////////////////////////////////////////////////////////////////
}
}
// 注销网络事件
WSAEventSelect(hSocket, (WSAEVENT) hConnectEvent, 0);
CloseHandle(hConnectEvent);
return (iConnectResult);
}
///////////////////////////////////////////////////////////
//
// 引入该函数的目的是为了避免NT下对域名解析的CACHE造成的问题
//
///////////////////////////////////////////////////////////
DWORD WINAPI DNSThread( LPVOID pParam )
{
DWORD dwIP = INADDR_NONE;
PHOSTENT pHost = gethostbyname( (char *)pParam );
if(pHost == NULL)
return INADDR_NONE;
dwIP = inet_addr( inet_ntoa(*(IN_ADDR *)*pHost->h_addr_list) );
return dwIP;
}
DWORD TE_GetIP(const char* name,BOOL fFixNtDNS /* = FALSE*/) // Used to Fix NT DNS Problem
{
DWORD dwIP = inet_addr(name);
if( dwIP != INADDR_NONE )
return dwIP;
if( fFixNtDNS )
{
OSVERSIONINFO osVersion;
osVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if( GetVersionEx(&osVersion) )
{
if(osVersion.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
DWORD dwThreadId = 0;
HANDLE hThread = CreateThread(NULL,0,DNSThread,(LPVOID)name,0,&dwThreadId);
if( hThread != NULL)
{
WaitForSingleObject(hThread,INFINITE);
if( GetExitCodeThread(hThread,&dwIP))
return dwIP;
}
}
}
}
PHOSTENT pHost = gethostbyname(name);
if(pHost == NULL)
return INADDR_NONE;
dwIP = inet_addr( inet_ntoa(*(IN_ADDR *)*pHost->h_addr_list) );
return dwIP;
}
// 建立连接(扩展函数)
int TE_ConnectEx(SOCKET hSocket, char const * pszServer, int nPort,DWORD dwTimeout,BOOL fFixNtDNS /*= FALSE*/)
{
/////////////////////////////////////////////////////////////////////////////
SOCKADDR_IN sockAddr;
ZeroMemory(&sockAddr,sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons((u_short)nPort);
sockAddr.sin_addr.s_addr = TE_GetIP(pszServer,fFixNtDNS);
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
{
TE_SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
//////////////////////////////////////////////////////////////////////
return TE_Connect(hSocket, (SOCKADDR *)&sockAddr,sizeof(sockAddr),dwTimeout);
}
// 绑定套接字
int TE_BindSocket(SOCKET hSocket, const struct sockaddr * SockName, int iNameLen)
{
if (bind(hSocket, SockName, iNameLen) == SOCKET_ERROR)
{
TE_SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
return (SOCKET_SUCCESS);
}
// 绑定套接字
int TE_BindSocketEx(SOCKET hSocket,int nPort)
{
SOCKADDR_IN sockAddr;
ZeroMemory(&sockAddr,sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
sockAddr.sin_port = htons((u_short)nPort);
return TE_BindSocket(hSocket,(SOCKADDR *)&sockAddr, sizeof(sockAddr));
}
// 监听套接字
int TE_ListenSocket(SOCKET hSocket, int iConnections)
{
if(listen(hSocket, iConnections) == SOCKET_ERROR)
{
TE_SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
return (SOCKET_SUCCESS);
}
// 接受套接字连接
SOCKET TE_Accept(SOCKET hSocket, struct sockaddr * pSocketAddress, int *iNameLen,DWORD dwTimeout)
{
HANDLE hAcceptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hAcceptEvent == NULL)
{
TE_SetLastError( (int)GetLastError() );
return (INVALID_SOCKET);
}
// 注册FD_ACCEPT事件
if( WSAEventSelect(hSocket, (WSAEVENT) hAcceptEvent, FD_ACCEPT) == SOCKET_ERROR)
{
CloseHandle(hAcceptEvent);
TE_SetLastError( WSAGetLastError() );
return (INVALID_SOCKET);
}
SOCKET hSocketAccept = WSAAccept(hSocket, pSocketAddress, iNameLen, NULL, 0);
int iConnectError = WSAGetLastError();
if ((hSocketAccept == INVALID_SOCKET) && (iConnectError == WSAEWOULDBLOCK))
{
// 阻塞
DWORD dwWaitResult = WSAWaitForMultipleEvents(1, &hAcceptEvent, TRUE,dwTimeout, TRUE);
if (dwWaitResult == WSA_WAIT_EVENT_0)
{
//////////////////////////////////////////////////////////////
/// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该
/// 进一步检查网络是否发生错误
///////////////////////////////////////////////////////////////
WSANETWORKEVENTS NetEvent;
if(WSAEnumNetworkEvents(hSocket,hAcceptEvent,&NetEvent) == SOCKET_ERROR)
TE_SetLastError( WSAGetLastError() );
else if(NetEvent.iErrorCode[FD_ACCEPT_BIT] !=0 ) // 发生错误
TE_SetLastError( NetEvent.iErrorCode[FD_ACCEPT_BIT] );
else
hSocketAccept = WSAAccept(hSocket, pSocketAddress, iNameLen, NULL, 0);
}
else
TE_SetLastError( WSAGetLastError() );
}
// 注销网络事件
WSAEventSelect(hSocket, (WSAEVENT) hAcceptEvent, 0);
CloseHandle(hAcceptEvent);
if (hSocketAccept != INVALID_SOCKET)
{
// 设置套接字的属性为地址可重用并且为非阻塞的
if ( (TE_BlockSocket(hSocketAccept, 0) == SOCKET_ERROR ) ||
(TE_SetSocketOption(hSocketAccept) == SOCKET_ERROR ) )
{
TE_CloseSocket(hSocketAccept,TRUE);
return (INVALID_SOCKET);
}
}
return (hSocketAccept);
}
// 接受套接字连接(允许中断)
SOCKET TE_AcceptEx(SOCKET hSocket, struct sockaddr * pSockName, int *iNameLen,HANDLE hEndEvent,DWORD dwTimeout /*= TE_DEFAULT_TIMEOUT*/)
{
if( hEndEvent == NULL)
return TE_Accept(hSocket,pSockName,iNameLen,dwTimeout);
HANDLE hAcceptEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hAcceptEvent == NULL)
{
TE_SetLastError( (int)GetLastError() );
return (INVALID_SOCKET);
}
WSAEVENT hEvent[2];
hEvent[0] = (WSAEVENT)hAcceptEvent;
hEvent[1] = (WSAEVENT)hEndEvent;
// 注册FD_ACCEPT事件
if( WSAEventSelect(hSocket, (WSAEVENT) hAcceptEvent, FD_ACCEPT) == SOCKET_ERROR)
{
CloseHandle(hAcceptEvent);
TE_SetLastError( WSAGetLastError() );
return (INVALID_SOCKET);
}
SOCKET hSocketAccept = WSAAccept(hSocket, pSockName, iNameLen, NULL, 0);
int iConnectError = WSAGetLastError();
if ((hSocketAccept == INVALID_SOCKET) && (iConnectError == WSAEWOULDBLOCK))
{
// 阻塞
DWORD dwWaitResult = WSAWaitForMultipleEvents(2, hEvent, FALSE,dwTimeout, TRUE);
if (dwWaitResult == WSA_WAIT_EVENT_0)
{
//////////////////////////////////////////////////////////////
/// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该
/// 进一步检查网络是否发生错误
///////////////////////////////////////////////////////////////
WSANETWORKEVENTS NetEvent;
if(WSAEnumNetworkEvents(hSocket,hAcceptEvent,&NetEvent) == SOCKET_ERROR)
TE_SetLastError( WSAGetLastError() );
else if(NetEvent.iErrorCode[FD_ACCEPT_BIT] !=0 ) // 发生错误
TE_SetLastError( NetEvent.iErrorCode[FD_ACCEPT_BIT] );
else
hSocketAccept = WSAAccept(hSocket, pSockName, iNameLen, NULL, 0);
}
else
TE_SetLastError( WSAGetLastError() );
}
// 注销网络事件
WSAEventSelect(hSocket, (WSAEVENT) hAcceptEvent, 0);
CloseHandle(hAcceptEvent);
if (hSocketAccept != INVALID_SOCKET)
{
// 设置套接字的属性为地址可重用并且为非阻塞的
if ( (TE_BlockSocket(hSocketAccept, 0) < 0) ||
(TE_SetSocketOption(hSocketAccept) < 0) )
{
TE_CloseSocket(hSocketAccept,TRUE);
return (INVALID_SOCKET);
}
}
return (hSocketAccept);
}
// 设置套接字是否为阻塞的
int TE_BlockSocket(SOCKET hSocket, BOOL bBlock)
{
u_long IoctlLong = (bBlock) ? 0 : 1;
if (ioctlsocket(hSocket, FIONBIO, &IoctlLong) == SOCKET_ERROR)
{
TE_SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
return (SOCKET_SUCCESS);
}
// 数据报接收函数
int TE_RecvDataFrom( SOCKET hSocket, struct sockaddr * pFrom, int iFromlen,
char *pszBuffer, int iBufferSize, DWORD dwTimeout)
{
HANDLE hReadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hReadEvent == NULL)
{
TE_SetLastError((int)GetLastError() );
return (SOCKET_ERROR);
}
DWORD dwRtxBytes = 0,
dwRtxFlags = 0;
WSABUF WSABuff;
ZeroMemory(&WSABuff,sizeof(WSABUF));
WSABuff.len = iBufferSize;
WSABuff.buf = pszBuffer;
for (;;)
{
// 注册FD_READ事件
if( WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, FD_READ) == SOCKET_ERROR)
{
CloseHandle(hReadEvent);
TE_SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
DWORD dwWaitResult = WSAWaitForMultipleEvents(1, &hReadEvent, TRUE, dwTimeout, TRUE);
if( dwWaitResult != WSA_WAIT_EVENT_0 )
{
// 注销事件
WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0);
CloseHandle(hReadEvent);
TE_SetLastError( WSAGetLastError());
return (SOCKET_ERROR);
}
//////////////////////////////////////////////////////////////
/// 注意:即使 dwWaitResult == WSA_WAIT_EVENT0 ,也应该
/// 进一步检查网络是否发生错误
///////////////////////////////////////////////////////////////
WSANETWORKEVENTS NetEvent;
if(WSAEnumNetworkEvents(hSocket,(WSAEVENT)hReadEvent,&NetEvent) == SOCKET_ERROR)
{
// 注销事件
WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0);
CloseHandle(hReadEvent);
TE_SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
if(NetEvent.iErrorCode[FD_READ_BIT] !=0 ) // 发生错误
{
// 注销事件
WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0);
CloseHandle(hReadEvent);
TE_SetLastError(NetEvent.iErrorCode[FD_READ_BIT]);
return (SOCKET_ERROR);
}
////////////////////////////////////////////////////////////////
// 注销事件
WSAEventSelect(hSocket, (WSAEVENT) hReadEvent, 0);
int FromLen = iFromlen;
if ( WSARecvFrom(hSocket, &WSABuff, 1, &dwRtxBytes, &dwRtxFlags,pFrom, &FromLen, NULL, NULL) == SOCKET_SUCCESS )
break;
if ( WSAGetLastError() != WSAEWOULDBLOCK)
{
CloseHandle(hReadEvent);
TE_SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
///////////////////////////////////////////////////////////////////////////
// 睡眠一段时间
//////////////////////////////////////////////////////////////////////////
Sleep(TE_BLOCKED_SNDRCV_SLEEP);
}
CloseHandle(hReadEvent);
return ((int) dwRtxBytes);
}
// 数据报发送数据报
int TE_SendDataTo(SOCKET hSocket, const struct sockaddr * pTo,int iToLen,
char const * pszBuffer, int iBufferSize, DWORD dwTimeout)
{
HANDLE hWriteEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hWriteEvent == NULL)
{
TE_SetLastError( (int)GetLastError() );
return (SOCKET_ERROR);
}
DWORD dwRtxBytes = 0,
dwRtxFlags = 0;
WSABUF WSABuff;
ZeroMemory(&WSABuff,sizeof(WSABUF));
WSABuff.len = iBufferSize;
WSABuff.buf = (char *) pszBuffer;
for (;;)
{
if (WSASendTo( hSocket, &WSABuff, 1, &dwRtxBytes, dwRtxFlags,pTo, iToLen, NULL, NULL) == SOCKET_SUCCESS)
break;
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
CloseHandle(hWriteEvent);
TE_SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -