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

📄 iotcpmodule.cc

📁 五行MMORPG引擎系统V1.0
💻 CC
字号:
// SimpleTCPIOModule.cpp: implementation of the IOTCPModule class.
//
//////////////////////////////////////////////////////////////////////
//#include <platforms.h>




#include <winsock.h>
#include "server/strhandle.h"
#include "server/net/IOTCPModule.h"
#include "platform/event.h"

namespace CS
{


typedef struct __tcpsocket 
{
	SOCKET		sock;
	SOCKADDR_IN		sockAddr;//rmt;
	char				szAddr[ADDR_MAX];
} TCPSOCKET;



//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
//CS_IOHANDLER IOTCPModule::m_ioHandler;
static IOTCPModule gs_tcpIOModule;

IOTCPModule::IOTCPModule()
{
	m_ioHandler.pGetError	= GetError;
	m_ioHandler.pClose		= Close;
	m_ioHandler.pConnect	= Connect;
	m_ioHandler.pFree		= Free;
	m_ioHandler.pListen	= Listen;
	m_ioHandler.pCheckAccept	= CheckAccept;
	m_ioHandler.pCheckSend	= CheckSend;
	m_ioHandler.pCheckRecv	= CheckRecv;
	m_ioHandler.pAccept	= Accept;
	m_ioHandler.pQuery		= Query;
	m_ioHandler.pRecvEx	= RecvEx;
	m_ioHandler.pSendEx	= SendEx;
	m_ioHandler.pRecv		= Recv;
	m_ioHandler.pSend		= Send;
	m_ioHandler.pInsert	= Insert;
	m_ioHandler.pRemove	= Remove;
	m_ioHandler.pGetConnectAddr	= GetConnectAddr;
	m_ioHandler.pGetNetAddress	= GetNetAddress;
}

IOTCPModule::~IOTCPModule()
{
}


CS_IOHANDLER* IOTCPModule::GetIOHandler()
{
	return &gs_tcpIOModule.m_ioHandler;
	//return &m_ioHandler;
}


INT	RPGAPI IOTCPModule::GetError(void *data)
{
	data;
	return WSAGetLastError();
}


int RPGAPI IOTCPModule::Insert()
{
	// Initialize Winsock 1.1
	WSADATA wsaData;
	if(WSAStartup(MAKEWORD(1,1), &wsaData)!=0) 
		return E_IOFAILED;

	if(LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) 
	{
		WSACleanup();
		return E_IOFAILED;
	}
	
	return E_IOOK;
}

int RPGAPI IOTCPModule::Remove()
{
	// Clean up Winsock 1.1
	WSACleanup();
	return E_IOOK;
}



void * RPGAPI IOTCPModule::Listen(char *svTarget)
{
	TCPSOCKET *tcps;

	////////////////////////////////////////////////////////
	//address port处理
	// Get listen port


	int		nPort=0;
	in_addr	bindAddr;
	bindAddr.S_un.S_addr = INADDR_ANY;

	if(svTarget==NULL) 
	{
		//nPort=CConfig::GetCfgNum(CConfig::m_szTCPIOConfig,"Default Port");
		return NULL;
	}
	else if(stricmp(svTarget,"RANDOM") != 0) 
	{
		char svAdr[260],*svPort;

		strncpy(svAdr,svTarget,260);
		svPort = BreakString(svAdr,":");
		if(svPort==NULL) 
			nPort=atoi(svAdr);
		else 
		{
			bindAddr.S_un.S_addr = inet_addr(svAdr);
			nPort	= atoi(svPort);
		}
	}//else
	

	///////////////////////////////////////////////////
	//生成监听socket
	// Create listener socket
	SOCKET sock;
	sock	= socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);

	if(sock==INVALID_SOCKET)
		return NULL;
	
	BOOL bValue;
	bValue = TRUE;
	setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,(char *)&bValue,sizeof(BOOL));
	bValue=TRUE;
	setsockopt(sock,SOL_SOCKET,SO_DONTLINGER,(char *)&bValue,sizeof(BOOL));
	


	///////////////////////////////////////////////////
	//绑定socket、启动socket监听
	// Bind socket and listen
	SOCKADDR_IN		sockAddr;
	dMemset(&sockAddr,0,sizeof(SOCKADDR_IN));

	sockAddr.sin_addr		= bindAddr;
	sockAddr.sin_family	= AF_INET;
	sockAddr.sin_port		= htons((WORD)nPort);
	
	if(bind(sock,(SOCKADDR *) &sockAddr,sizeof(SOCKADDR_IN)) == SOCKET_ERROR) 
	{
		closesocket(sock);
		return NULL;
	}

	if(listen(sock,SOMAXCONN) != 0) 
	{
		closesocket(sock);
		return NULL;
	}
	
	int namelen = sizeof(SOCKADDR_IN);
	getsockname(sock, (SOCKADDR *)&sockAddr, &namelen);

	// Allocate state structure
	tcps = (TCPSOCKET*)dMalloc(sizeof(TCPSOCKET));
	if(tcps==NULL) 
	{
		closesocket(sock);
		return NULL;
	}


	// Fill in state structure
	tcps->sock	= sock;
	dMemset(&(tcps->sockAddr), 0, sizeof(SOCKADDR_IN));
	
	///////////////////////////////////////////
	//获取连接后IP地址
	// Get connect address
	if(bindAddr.S_un.S_addr == INADDR_ANY) 
	{
		char svHostName[ADDR_MAX];
		hostent *he;
		in_addr *pAddr;

		gethostname(svHostName,ADDR_MAX);
		he	= gethostbyname(svHostName);
		if(he) 
		{
			pAddr	= (in_addr*)he->h_addr_list[0];
			dSprintf(tcps->szAddr,ADDR_MAX,"%u.%u.%u.%u:%u",
						pAddr->S_un.S_un_b.s_b1,
						pAddr->S_un.S_un_b.s_b2,
						pAddr->S_un.S_un_b.s_b3,
						pAddr->S_un.S_un_b.s_b4,
						ntohs(sockAddr.sin_port));
		} 
		else 
		{
			strcpy(tcps->szAddr,"No Connect Addr");
		}
	}
	else 
	{
		strncpy(tcps->szAddr,svTarget,ADDR_MAX);
	}
	return tcps;
}



BOOL RPGAPI IOTCPModule::CheckAccept(void *data)
{
	// Check to see if this is a listening socket
	TCPSOCKET *tcps = (TCPSOCKET*)data;
	
	//检测是否有连接请求
	// Check for connection
	fd_set	rdfds;
	TIMEVAL	tm = {0,0};

	FD_ZERO(&rdfds);
	FD_SET(tcps->sock,&rdfds);

	return select(0,&rdfds,NULL,NULL,&tm) > 0;
}


void * RPGAPI IOTCPModule::Accept(void *data, char *svAddr, int nMaxLen)
{
	TCPSOCKET *tcps = (TCPSOCKET*)data;

	//接受新的socket请求
	// Accept socket
	SOCKADDR_IN sockAddr;
	int			len = sizeof(SOCKADDR_IN);
	SOCKET		sockNew;

	sockNew = accept(tcps->sock, (SOCKADDR*)&sockAddr, &len);
	if(sockNew==INVALID_SOCKET)
		return NULL;

	BOOL bValue;
	bValue = TRUE;
	setsockopt(sockNew, IPPROTO_TCP, TCP_NODELAY, (char*)&bValue, sizeof(BOOL));
	bValue=TRUE;
	setsockopt(sockNew, SOL_SOCKET, SO_DONTLINGER, (char*)&bValue, sizeof(BOOL));
	

	//新建IO Socket对象
	TCPSOCKET *ioSockNew = (TCPSOCKET*)dMalloc(sizeof(TCPSOCKET));
	if(ioSockNew==NULL) 
	{
		closesocket(sockNew);
		return NULL;
	}

	ioSockNew->sock		= sockNew;
	ioSockNew->sockAddr	= sockAddr;
	
	//返回地址信息
	if(nMaxLen > 16) 
	{
		dSprintf(svAddr,ADDR_MAX, "%3u.%3u.%3u.%3u",
			sockAddr.sin_addr.S_un.S_un_b.s_b1,
			sockAddr.sin_addr.S_un.S_un_b.s_b2,
			sockAddr.sin_addr.S_un.S_un_b.s_b3,
			sockAddr.sin_addr.S_un.S_un_b.s_b4);
	}
		
	return ioSockNew;
}


void * RPGAPI IOTCPModule::Connect(char *svTarget)
{
	//新建socket
	// Create socket
	SOCKET sock;
	sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if(sock==INVALID_SOCKET)
		return NULL;

	BOOL bValue;
	bValue = TRUE;
	setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&bValue, sizeof(BOOL));
	bValue = TRUE;
	setsockopt(sock, SOL_SOCKET, SO_DONTLINGER, (char*)&bValue, sizeof(BOOL));
	

	//分解连接IP、端口
	// Get target port
	int	nPort;
	char	svHost[ADDR_MAX],
			*pPort;

	strncpy(svHost,svTarget,ADDR_MAX);
	for(pPort=svHost; ((*pPort)!=':') && ((*pPort)!=NULL); pPort++);
	if((*pPort)==':') 
	{
		*pPort = '\0';
		pPort++;
		nPort  = atoi(pPort);
	}
	else 
		return NULL;//nPort=CConfig::GetCfgNum(CConfig::m_szTCPIOConfig,"Default Port");


	//解析IP地址
	// Resolve hostname
	DWORD addr = inet_addr(svHost);
	if(addr==INADDR_NONE) 
	{
		hostent *he = gethostbyname(svHost);
		if(he==NULL) 
		{
			closesocket(sock);
			return NULL;
		}
		addr = *(DWORD*)(he->h_addr_list[0]);
	}


	//创建IP地址信息
	// Create socket address
	SOCKADDR_IN  sockAddr;
	dMemset(&sockAddr,0,sizeof(SOCKADDR_IN));

	sockAddr.sin_addr.S_un.S_addr	= addr;
	sockAddr.sin_family				= AF_INET;
	sockAddr.sin_port					= htons((WORD)nPort);
	

	//连接远程主机
	// Connect to remote host
	if( connect(sock,(SOCKADDR *)&sockAddr,sizeof(SOCKADDR_IN)) == SOCKET_ERROR) 
	{
		closesocket(sock);
		return NULL;
	}
	
	//返回TCPSocket信息
	// Allocate internal state structure
	TCPSOCKET *tcps = (TCPSOCKET*)dMalloc(sizeof(TCPSOCKET));
	if(tcps==NULL) 
	{
		closesocket(sock);
		return NULL;
	}
	
	tcps->sock		= sock;
	tcps->sockAddr	= sockAddr;
	
	return tcps;
}



int RPGAPI IOTCPModule::Close(void *ios)
{
	TCPSOCKET *tcps = (TCPSOCKET*)ios;
	
	closesocket(tcps->sock);

	dFree(tcps);
	return E_IOOK;
}


char * RPGAPI IOTCPModule::Query()
{
	return "TCPIO: TCP IO Module v1.0";
}



BOOL RPGAPI IOTCPModule::CheckRecv(void *data)
{
	TCPSOCKET *tcps = (TCPSOCKET *)data;
	
	// Check socket for readability 
	TIMEVAL	tv = {0,0};
	fd_set	rfds;
	int		nRet;

	FD_ZERO(&rfds);
	FD_SET(tcps->sock,&rfds);
	nRet = select(1,&rfds,NULL,NULL,&tv);//WSAENOTINITIALISED

	return (nRet > 0);
}


int RPGAPI IOTCPModule::Recv(void *data, BYTE *pInData, int *pnInDataLen)
{
	TCPSOCKET *tcps = (TCPSOCKET *)data;
	//获取数据长度
	// Get length of rest of data
	int	nRet;
	int	nPacketSize;

	//nPacketSize	= *pnInDataLen;
	int	nLenRecv;
	//nLenRecv = recv(tcps->sock, (char*)&nPacketSize, sizeof(int), MSG_PEEK);
	//if(nLenRecv <= 0) 
	//	return SOCKET_ERROR;
	//if(nLenRecv < sizeof(int)) 
	//	return 0;

	//确保有数据存在
	// Make sure we have the rest of the packet
	DWORD len;
	if(ioctlsocket(tcps->sock, FIONREAD, &len) == SOCKET_ERROR) 
		return E_IOFAILED;

	if(len > *pnInDataLen || len > MaxPacketDataSize) 
		return E_IOINVALID;

	nPacketSize = len;
	//请除头信息
	// Clear off the header
	//nLenRecv = recv(tcps->sock, (char*)&nPacketSize, sizeof(int), 0);
	//if(nLenRecv < sizeof(int)) 
	//	return SOCKET_ERROR;
	
	//申请数据缓冲
	// Allocate buffer for data
	//BYTE	*pBuffer = (BYTE*) dMalloc(nPacketSize);
	//if(pBuffer == NULL) 
	//{
	//	*pInData		= NULL;
	//	*pnInDataLen= 0;
	//	return SOCKET_ERROR;
	//}


	BYTE	*pBuffer = pInData;
	//接受数据包
	// Receive data
	char *pBufRecv	= (char*) pBuffer;
	int nLeftNum	= nPacketSize;
	do 
	{
		nLenRecv = recv(tcps->sock, pBufRecv, nLeftNum, 0);
		if(nLenRecv == SOCKET_ERROR) 
		{
			dFree(pBuffer);
			*pInData		= NULL;
			*pnInDataLen= 0;
			return E_IOFAILED;
		}
		nLeftNum	-= nLenRecv;
		pBufRecv	+= nLenRecv;
		if(nLeftNum > 0)
			Sleep(RECV_IDLE);

	} while(nLeftNum > 0);

	// Pass data back to application
	//*pInData		= pBuffer;
	*pnInDataLen= nPacketSize;
	return E_IOOK;
}


int RPGAPI IOTCPModule::RecvEx(void *data, BYTE **pInData, int *pnInDataLen)
{
	TCPSOCKET *tcps = (TCPSOCKET *)data;
	//获取数据长度
	// Get length of rest of data
	int		nRet;
	int	nPacketSize;
	int	nLenRecv;
	nLenRecv = recv(tcps->sock, (char*)&nPacketSize, sizeof(int), MSG_PEEK);
	if(nLenRecv <= 0) 
		return E_IOFAILED;
	if(nLenRecv < sizeof(int)) 
		return E_IOINVALID;

	//确保有数据存在
	// Make sure we have the rest of the packet
	DWORD len;
	if(ioctlsocket(tcps->sock, FIONREAD, &len) == SOCKET_ERROR) 
		return E_IOFAILED;

	if(len < (sizeof(int) + nPacketSize)) 
		return E_IOINVALID;

	//请除头信息
	// Clear off the header
	nLenRecv = recv(tcps->sock, (char*)&nPacketSize, sizeof(int), 0);
	if(nLenRecv < sizeof(int)) 
		return E_IOFAILED;
	
	//申请数据缓冲
	// Allocate buffer for data
	BYTE	*pBuffer = (BYTE*) dMalloc(nPacketSize);
	if(pBuffer == NULL) 
	{
		*pInData		= NULL;
		*pnInDataLen= 0;
		return E_IOFAILED;
	}


	//接受数据包
	// Receive data
	char *pBufRecv	= (char*) pBuffer;
	int nLeftNum	= nPacketSize;
	do 
	{
		nLenRecv = recv(tcps->sock, pBufRecv, nLeftNum, 0);
		if(nLenRecv == SOCKET_ERROR) 
		{
			dFree(pBuffer);
			*pInData		= NULL;
			*pnInDataLen= 0;
			return E_IOFAILED;
		}
		nLeftNum	-= nLenRecv;
		pBufRecv	+= nLenRecv;
		if(nLeftNum > 0)
			Sleep(RECV_IDLE);

	} while(nLeftNum > 0);

	// Pass data back to application
	*pInData		= pBuffer;
	*pnInDataLen= nPacketSize;
	return E_IOOK;
}


BOOL RPGAPI IOTCPModule::CheckSend(void *data)
{
	TCPSOCKET *tcps = (TCPSOCKET*)data;
	//发送数据包
	// Send packet
	TIMEVAL	tm;
	fd_set	wfds;
	int		ret;

	tm.tv_sec	= SEND_TIMEOUT;
	tm.tv_usec	= 0;

	FD_ZERO(&wfds);
	FD_SET(tcps->sock,&wfds);

	ret = select(0,NULL,&wfds,NULL,&tm);
	return (ret > 0);
}


int RPGAPI IOTCPModule::Send(void *data, BYTE *pData, int nDataLen)
{
	AssertWarn(nDataLen <= MaxPacketDataSize, "需要小于最大包大小...");
	int		ret;
	TCPSOCKET *tcps = (TCPSOCKET*)data;

	//生成单一数据包
	// Make single packet
	void *pBufPacket = pData;//dMalloc( sizeof(int) + nDataLen);
	if(pBufPacket == NULL) 
		return E_IOFAILED;

	//填充数据包长度、数据包内容
	// Send packet length
	//dMemcpy(pBufPacket, &nDataLen, sizeof(int));
	//dMemcpy((BYTE*)pBufPacket + sizeof(int), pData, nDataLen);
	
	{
		char	*pBufSend	= (char*)pBufPacket;
		int	nLeftNum		= nDataLen;//+sizeof(int);
		do 
		{
			ret = send(tcps->sock, pBufSend, nLeftNum, 0);
			if(ret==SOCKET_ERROR)
				break;

			nLeftNum	-= ret;
			pBufSend	+= ret;
			if(nLeftNum > 0)
				Sleep(SEND_IDLE);

		} while(nLeftNum > 0);

		//dFree(pBufPacket);
		if(ret==SOCKET_ERROR)
			return E_IOFAILED;
		return E_IOOK;
	}

	//dFree(pBufPacket);
	return ret;
}


int RPGAPI IOTCPModule::SendEx(void *data, BYTE *pData, int nDataLen)
{
	int		ret;
	TCPSOCKET *tcps = (TCPSOCKET*)data;

	//生成单一数据包
	// Make single packet
	void *pBufPacket = dMalloc( sizeof(int) + nDataLen);
	if(pBufPacket == NULL) 
		return E_IOFAILED;

	//填充数据包长度、数据包内容
	// Send packet length
	dMemcpy(pBufPacket, &nDataLen, sizeof(int));
	dMemcpy((BYTE*)pBufPacket + sizeof(int), pData, nDataLen);
	
	{
		char	*pBufSend	= (char*)pBufPacket;
		int	nLeftNum		= nDataLen+sizeof(int);
		do 
		{
			ret = send(tcps->sock, pBufSend, nLeftNum, 0);
			if(ret==SOCKET_ERROR)
				break;

			nLeftNum	-= ret;
			pBufSend	+= ret;
			if(nLeftNum > 0)
				Sleep(SEND_IDLE);

		} while(nLeftNum > 0);

		dFree(pBufPacket);
		if(ret==SOCKET_ERROR)
			return E_IOFAILED;
		return E_IOOK;
	}

	dFree(pBufPacket);
	return ret;
}


void RPGAPI IOTCPModule::Free(void *data, BYTE *pBuffer)
{
	if(pBuffer==NULL) 
		return;
	dFree(pBuffer);
}

void* RPGAPI IOTCPModule::GetNetAddress(void *data)
{
	TCPSOCKET *tcps = (TCPSOCKET*)data;
	return &tcps->sockAddr;
}


int RPGAPI IOTCPModule::GetConnectAddr(void *data, char *svAddr, int nMaxLen)
{
	TCPSOCKET *tcps = (TCPSOCKET*)data;

	if(nMaxLen < 0)
		return SOCKET_ERROR;
	if(nMaxLen > ADDR_MAX) 
		nMaxLen = ADDR_MAX;

	strncpy(svAddr, tcps->szAddr, nMaxLen);
	return E_IOOK;
}


};//namespace CS


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -