📄 socketmodel.cpp
字号:
/////////////////////////////////////////////////////////////////////////
Sleep(_BLOCKED_SNDRCV_SLEEP);
// 注册FD_WRITE事件
if( WSAEventSelect(hSocket, (WSAEVENT) hWriteEvent, FD_WRITE)
== SOCKET_ERROR)
{
CloseHandle(hWriteEvent);
SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
DWORD 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 CSocketModel::CloseSocket(SOCKET 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);
}
ZeroMemory(szBuffer,256);
//接收残留数据
nRecvResult = RecvLL(hSocket, szBuffer, sizeof(szBuffer));
} while (nRecvResult > 0);
if (hSocketEvent != NULL)
CloseHandle(hSocketEvent);
//不再允许接收和发送
shutdown(hSocket, SD_BOTH);
}
// 关闭套接字
closesocket(hSocket);
}
//阻塞ACCEPT,没有响应不返回
//入口:套接字,主机地址,长度
//出口:正确返回端口号,否则返回INVALID_SOCKET
SOCKET CSocketModel::Accept_Block(SOCKET hSocket, struct sockaddr * pSocketAddress,
int *nAddrLen)
{
ASSERT(hSocket!=NULL);
//int nLengthAddr = sizeof(SOCKADDR);
SOCKET hAccept = accept(hSocket, pSocketAddress, nAddrLen);
//如果该端口错误
if(hAccept == INVALID_SOCKET) {
SetLastError(WSAGetLastError());
}
return hAccept;
}
// 绑定套接字
//入口:套接字,绑定的地址信息,长度
//出口:正确0,错误-1
int CSocketModel::BindSocket(SOCKET hSocket, struct sockaddr * pSocketAddress,
int nAddrLen)
{
if (bind(hSocket, pSocketAddress, nAddrLen) == SOCKET_ERROR)
{
SetLastError( WSAGetLastError() );
return (SOCKET_ERROR);
}
return (SOCKET_SUCCESS);
}
// 绑定套接字
//入口:套接字,端口号
//出口:正确0,错误-1
int CSocketModel::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 BindSocket(hSocket,(SOCKADDR *)&sockAddr, sizeof(sockAddr));
}
//释放Winsock2动态连接库
void CSocketModel::CleanupLibrary(void)
{
WSACleanup();
}
//注册WINSOCK2.2DLL
int CSocketModel::InitLibrary(void)
{
WSADATA WSD;
WORD wVersionRequired = MAKEWORD( _SOCKET_MAJOR_VERSION,
_SOCKET_MINOR_VERSION );
ZeroMemory(&WSD,sizeof(WSADATA));
int nErrorNo = WSAStartup(wVersionRequired, &WSD);
if ( SOCKET_SUCCESS != nErrorNo )
{
SetLastError( nErrorNo );
return ( SOCKET_ERROR );
}
if ( LOBYTE( WSD.wVersion ) != _SOCKET_MINOR_VERSION ||
HIBYTE( WSD.wVersion ) != _SOCKET_MAJOR_VERSION )
{
WSACleanup( );
SetLastError( WSAVERNOTSUPPORTED );
return (SOCKET_ERROR);
}
//成功初始化
return (SOCKET_SUCCESS);
}
// 建立连接
//入口:套接字,地址结构,结构长度,超时
//出口:SOCKET_SUCCESS/SOCKET_ERROR
int CSocketModel::Connect_Event(SOCKET hSocket, const struct sockaddr * pSocketAddress,
int nAddrLen,DWORD 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))
{
DWORD 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 CSocketModel::Connect_Block(SOCKET hSocket, const struct sockaddr * pSocketAddress,
int nAddrLen)
{
ASSERT(hSocket!=NULL);
if(hSocket==NULL)
return SOCKET_ERROR;
if(connect(hSocket, pSocketAddress, nAddrLen) == SOCKET_ERROR)
return SOCKET_ERROR;
return SOCKET_SUCCESS;
}
//创建具有重叠IO能力的套接字
//入口:协议,协议类型(TCP/U),协议
//出口:返回创建的重叠IO SOCKET
//注意:使用SOCKET()函数创建的套接字默认具有重叠IO能力
SOCKET CSocketModel::CreateSocket(int nAddressFamily /*= AF_INET*/,
int nType/*= SOCK_STREAM*/,
int nProtocol/*= 0*/)
{
SOCKET 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);
}
// 监听套接字
//入口:套接字,接入的等待队列长度
//出口:SOCKET_ERROR/SOCKET_SUCCESS
int CSocketModel::ListenSocket(SOCKET 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 + -