📄 winiosocketex.cpp
字号:
// 数据报发送数据报
int IOSocketEx::SendTo_Event(SLSocket hSocket, sockaddr * pTo,
int nAddrLen,char const * pszBuffer,
int nBufferSize, U32 dwTimeout)
{
HANDLE hWriteEvent = CreateEvent(NULL, false, false, NULL);
if (hWriteEvent == NULL)
{
SetLastError( (int)GetLastError() );
return (SOCKET_ERROR);
}
DWORD dwRtxBytes = 0,
dwRtxFlags = 0;
WSABUF WSABuff;
dMemset(&WSABuff,sizeof(WSABUF), 0);
WSABuff.len = nBufferSize;
WSABuff.buf = (char *) pszBuffer;
for (;;)
{
int nRet = WSASendTo( hSocket, &WSABuff, 1, &dwRtxBytes, dwRtxFlags, pTo, nAddrLen, NULL, NULL);
if (nRet == SOCKET_SUCCESS)
break;
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
CloseHandle(hWriteEvent);
SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
//////////////////////////////////////////////////////////////////////////
// 睡眠一段时间
/////////////////////////////////////////////////////////////////////////
Sleep(_BLOCKED_SNDRCV_SLEEP);
// 注册FD_WRITE事件
if( WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, FD_WRITE)
== SOCKET_ERROR)
{
CloseHandle(hWriteEvent);
SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
U32 dwWaitResult = WSAWaitForMultipleEvents
(1, &hWriteEvent, TRUE,dwTimeout, TRUE);
if( dwWaitResult != WSA_WAIT_EVENT_0 )
{
// 注销事件
WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0);
CloseHandle(hWriteEvent);
SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
WSANETWORKEVENTS NetEvent;
if(WSAEnumNetworkEvents(hSocket,(WSAEVENT)hWriteEvent,&NetEvent) == SOCKET_ERROR)
{
// 注销事件
WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0);
CloseHandle(hWriteEvent);
SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
if(NetEvent.iErrorCode[FD_WRITE_BIT] !=0 ) // 发生错误
{
// 注销事件
WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0);
CloseHandle(hWriteEvent);
SetLastError(NetEvent.iErrorCode[FD_WRITE_BIT]);
return (SOCKET_ERROR);
}
////////////////////////////////////////////////////////////////
// 注销事件
WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, 0);
}
CloseHandle(hWriteEvent);
return ((int) dwRtxBytes);
}
//关闭套接字
//入口:套接字,是否强行关闭(如果bHardClose==false,那么接收剩余的数据后关闭连接)
void IOSocketEx::CloseSocket(SLSocket hSocket, bool bHardClose)
{
// 不需要捕获错误
if (!bHardClose) // 优雅关闭 Graceful close
{
// 不再发送数据,对于TCP套接字,在所有的数据都发送完毕之后,
// 将发送一个 FIN ,通知接收方所有数据已经发送完毕。
shutdown(hSocket, SD_SEND);
// 接收缓冲区有可能还有未接收的数据,在关闭套接字之前应该先
// 读取残留的数据。
int nRecvResult;
HANDLE hSocketEvent = CreateEvent(NULL, false, false, NULL);
//为残留数据提供的缓冲区
char szBuffer[256];
do
{
if (hSocketEvent != NULL)
{
//注册网络事件
WSAEventSelect(hSocket,(WSAEVENT) hSocketEvent, FD_READ | FD_CLOSE);
WSAWaitForMultipleEvents(1,&hSocketEvent, TRUE,_SHUTDOWN_RECV_TIMEOUT, TRUE);
//清除网络事件
WSAEventSelect(hSocket, (WSAEVENT) hSocketEvent, 0);
}
dMemset(szBuffer,256, 0);
//接收残留数据
nRecvResult = RecvLL(hSocket, szBuffer, sizeof(szBuffer));
} while (nRecvResult > 0);
if (hSocketEvent != NULL)
CloseHandle(hSocketEvent);
//不再允许接收和发送
shutdown(hSocket, SD_BOTH);
}
// 关闭套接字
closesocket(hSocket);
}
//阻塞ACCEPT,没有响应不返回
//入口:套接字,主机地址,长度
//出口:正确返回端口号,否则返回INVALID_SOCKET
SLSocket IOSocketEx::Accept_Block(SLSocket hSocket, sockaddr * pSocketAddress, int *nAddrLen)
{
AssertWarn(hSocket,"Socket句柄为NULL")
//int nLengthAddr = sizeof(SOCKADDR);
SLSocket hAccept = ::accept(hSocket, pSocketAddress, nAddrLen);
//如果该端口错误
if(hAccept == INVALID_SOCKET) {
SetLastError(WSAGetLastError());
}
return hAccept;
}
// 绑定套接字
//入口:套接字,绑定的地址信息,长度
//出口:正确0,错误-1
int IOSocketEx::BindSocket(SLSocket hSocket, sockaddr * pSocketAddress,
int nAddrLen)
{
if (bind(hSocket, pSocketAddress, nAddrLen) == SOCKET_ERROR)
{
SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
return (SOCKET_SUCCESS);
}
// 绑定套接字
//入口:套接字,端口号
//出口:正确0,错误-1
int IOSocketEx::BindSocketEx(SLSocket hSocket,int nPort)
{
SOCKADDR_IN sockAddr;
dMemset(&sockAddr,sizeof(sockAddr), 0);
sockAddr.sin_family = AF_INET;
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
sockAddr.sin_port = htons((u_short)nPort);
return BindSocket(hSocket,(SOCKADDR *)&sockAddr, sizeof(sockAddr));
}
// 建立连接
//入口:套接字,地址结构,结构长度,超时
//出口:SOCKET_SUCCESS/SOCKET_ERROR
int IOSocketEx::Connect_Event(SLSocket hSocket, sockaddr * pSocketAddress, int nAddrLen,U32 dwTimeout)
{
HANDLE hConnectEvent = CreateEvent(NULL, false, false, NULL);
if (hConnectEvent == NULL)
{
SetLastError( (int)GetLastError() );
return (SOCKET_ERROR);
}
// 注册FD_CONNECT事件
if( WSAEventSelect(hSocket, (WSAEVENT) hConnectEvent, FD_CONNECT) == SOCKET_ERROR)
{
CloseHandle(hConnectEvent);
SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
int nConnectResult = WSAConnect(hSocket, pSocketAddress, nAddrLen, NULL, NULL, NULL, NULL);
int nConnectError = WSAGetLastError();
if((nConnectResult==SOCKET_ERROR) && (nConnectError == WSAEWOULDBLOCK))
{
U32 dwWaitResult = WSAWaitForMultipleEvents(1, &hConnectEvent, TRUE,dwTimeout, TRUE);
if (dwWaitResult != WSA_WAIT_EVENT_0)
{
SetLastError( WSAGetLastError() );
nConnectResult = SOCKET_ERROR;
}
else
{
WSANETWORKEVENTS NetEvent;
if(WSAEnumNetworkEvents(hSocket,(WSAEVENT)hConnectEvent,&NetEvent) == SOCKET_ERROR)
{
SetLastError( WSAGetLastError() );
nConnectResult = SOCKET_ERROR;
}
else if(NetEvent.iErrorCode[FD_CONNECT_BIT] !=0 ) // 发生错误
{
SetLastError( NetEvent.iErrorCode[FD_CONNECT_BIT] );
nConnectResult = SOCKET_ERROR;
}
else
nConnectResult = SOCKET_SUCCESS;
////////////////////////////////////////////////////////////////
}
}
// 注销网络事件
WSAEventSelect(hSocket, (WSAEVENT) hConnectEvent, 0);
CloseHandle(hConnectEvent);
return (nConnectResult);
}
int IOSocketEx::Connect_Block(SLSocket hSocket, sockaddr * pSocketAddress,
int nAddrLen)
{
AssertWarn(hSocket,"Socket句柄为NULL")
if(hSocket==NULL)
return SOCKET_ERROR;
if(connect(hSocket, pSocketAddress, nAddrLen) == SOCKET_ERROR)
return SOCKET_ERROR;
return SOCKET_SUCCESS;
}
//创建具有重叠IO能力的套接字
//入口:协议,协议类型(TCP/U),协议
//出口:返回创建的重叠IO SLSocket
//注意:使用SLSocket()函数创建的套接字默认具有重叠IO能力
SLSocket IOSocketEx::CreateSocket(int nAddressFamily , int nType, int nProtocol)
{
SLSocket hSocket = WSASocket(nAddressFamily, nType, nProtocol, NULL,0,WSA_FLAG_OVERLAPPED);
if ( hSocket == INVALID_SOCKET )
{
SetLastError( WSAGetLastError() );
return (INVALID_SOCKET);
}
//设置套接字选项
if ( SOCKET_ERROR == SetSocketOption(hSocket) ) //设置属性失败
{
CloseSocket(hSocket, TRUE);
return (INVALID_SOCKET);
}
return (hSocket);
}
SLSocket IOSocketEx::TCPSocket()
{
return CreateSocket(AF_INET, SOCK_STREAM);
}
SLSocket IOSocketEx::UDPSocket()
{
return CreateSocket(AF_INET, SOCK_DGRAM);
}
// 监听套接字
//入口:套接字,接入的等待队列长度
//出口:SOCKET_ERROR/SOCKET_SUCCESS
int IOSocketEx::ListenSocket(SLSocket hSocket, int nConnections)
{
if(listen(hSocket, nConnections) == SOCKET_ERROR)
{
SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
return (SOCKET_SUCCESS);
}
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -