⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winiosocketex.cpp

📁 五行MMORPG引擎系统V1.0
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 数据报发送数据报
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 + -