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

📄 internetport.h

📁 网络游戏魔域源代码 测试可以完整变异
💻 H
字号:
// 接口类。接口:基于消息通讯机制的网络间通讯接口。
// 仙剑修,2002.9.6

#ifndef	INTERNETPORT_H
#define INTERNETPORT_H

#pragma warning(disable:4786)

#define	_WINSOCKAPI_
#include <afxmt.h>
#ifndef FD_SETSIZE
#define	FD_SETSIZE					110	//? 可修改以增加节点数
#endif
#include "winsock2.h"
#include "I_MessagePort.h"
#include <list>
#include <vector>
using namespace std;

#include "MessagePort.h"		// 包含“通用定义”


/////////////////////////////////////////////////////////////////////////////////////////////////
// 外部定义
MSGPORT_BEGIN
#define	CONNECT_OVERTIMESECS		10					// 客户端OPEN等待超时秒数
#define	SOCKET_VERSION				0x0002				// 使用的WIN SOCKET版本号。0x0101、0x0002
#define	SNDBUF_SIZE					(32*1024)			// SOCKET系统内部SENDBUF尺寸

#define	IPSTR_SIZE	16
#define	MAX_KEYSIZE	256

#define	MASTER_PORT_ID				0					// 主节点号
#define	MAX_PORT_SIZE				FD_SETSIZE-2			// 最多多少节点

enum {	SYS_PACKET_BASE		= MAX_PACKET_ID+1,	// 系统消息包
		SYS_PACKET_PORTID	= SYS_PACKET_BASE+1,	// 向主节点发送自己的ID号(内容为INT)
		SYS_PACKET_PORTSIZE	= SYS_PACKET_BASE+2,	// 向子节点发送SIZE(内容为INT)。子节点SIZE不同时,修正自己的SIZE
		SYS_PACKET_LOGINKEY	= SYS_PACKET_BASE+3,	// 向主节点发送自己的LOGIN_KEY(内容为STRING)
};
MSGPORT_END
/////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////
// 内部结构
MSGPORT_BEGIN
const int	MSG_HEAD_SIZE		= 6;					// 消息头的尺寸
const int	RECV_BUFFER_SIZE	= 16*1024;				// 应用程序内部BUFFER尺寸。
struct	CMessageHead							// 注意:结构尺寸必须与MSG_HEAD_SIZE相同
{
	unsigned short		m_nPort;				// 子->主:TARGET_PORT,主->子:SOURCE_PORT
	unsigned short		m_nPacket;
	unsigned short		m_nVarType;
	char				m_bufData[1];
};
MSGPORT_END
/////////////////////////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////////////////////////
class	CInternetPort : private IMessagePort
{
private: // 内部类型
	// 输入BUFFER
	struct	CRecvBuffer{
	public:
		CRecvBuffer()	{ Reset(); }
		void Reset()	{ m_nMsgLen = 0; }
		bool DelMsg(int nLen){
						if(nLen <= m_nMsgLen){
							if(nLen < m_nMsgLen)
								memcpy(m_bufMsg, m_bufMsg + nLen, m_nMsgLen - nLen);
							m_nMsgLen -= nLen;
							return true;
						}
						m_nMsgLen	= 0;
						return false;
		}
		message_port::CMessageHead* GetHead()	{ return (message_port::CMessageHead*)m_bufMsg; }
		char* GetTail()	{ return m_bufMsg + m_nMsgLen; }
		int	  GetLen()	{ return m_nMsgLen; }
		void  AddLen(int nLen)	{ m_nMsgLen += nLen; }
	protected:
		char		m_bufMsg[message_port::RECV_BUFFER_SIZE];
		int			m_nMsgLen;
	};
public:
	CInternetPort			(int nPort);
	virtual ~CInternetPort	() { ClearPortSet(); }

	IMessagePort*	GetInterface() { return (IMessagePort*)this; }

protected: // Interface
	// 取本接口的ID号
	virtual int		GetSize	() { return m_nPortSize; }
	virtual int		GetID	() { return m_id; }

	// 初始化,设置接口ID号,开始接收消息。可重复调用(PORT_ID不能改变)。
	virtual bool	Open	();
	// 关闭接口,不再接收消息。可重复调用。客户端会等待CONNECT_OVERTIMESECS秒
	virtual bool	Close	();

	// 发送消息到指定接口。包含消息ID、数据类型、数据。return false: 发送不成功,或已经关闭
	virtual bool	Send	(int nPort, int nPacket, VAR_TYPE nVarType, const void* buf);
	// 接收指定接口(或所有接口)发来的消息。可指定消息ID,也可不指定。VARTYPE无意义。return false: 没有收到数据
	virtual bool	Recv	(int nPort, int nPacket, VAR_TYPE nVarType, void* buf, CMessageStatus *pStatus = NULL);

	// 检查消息栈中有没有消息,如没有消息则等待。return false: 超时或错误。
	virtual bool	WaitMsg	(int nMilliSec);						// ★可添加接口号和包类型参数,以等待某一消息。
//	virtual bool	Broadcast	(int nGroup, int nPacket, int nVarType, DWORD nData);
	virtual bool	IsOpen	() { return m_nState == STATE_OK; }

protected:
	bool	PushMsg		(int nPort, int nPacket, VAR_TYPE nVarType, const void* buf);
	bool	PopMsg		(int *nPort, int *nPacket, VAR_TYPE *nVarType, void* buf);
	bool	SendFrom	(int nPortFrom, int nPort, int nPacket, VAR_TYPE nVarType, const void* buf);
	bool	RecvMsg		(int nMilliSec);
	bool	RecvToBuf	(CRecvBuffer* pBuf, SOCKET sock);					// return false: error
	bool	BufferToList	(int idx);								// return false: 无消息
	static int	SIZE_OF_TYPE		(int type);
	SOCKET	CreateServerSocket		();
	SOCKET	CreateClientSocket		();

	// 由SET的函数调用
	bool	Init();			// WSAStartup
	void	Clear();		// WSACleanup

protected:
	int			m_id;
	enum { STATE_OK, STATE_CLOSED, STATE_OPENING };
	int			m_nState;
	typedef	list<message_port::CMessagePacket*>	MSG_SET;
	MSG_SET		m_setMsg;

////////////////////////////////////////////////////////////////////////////////////////
// 共用静态对象
// 所有接口的添加必须在首次通讯前完成。通讯期间接口集不会有变化。完成所有通讯后,才能清空接口。
// 注意:目前只支持“静态”接口集。
public: //static
	bool	InitPortSet(int nPortSize, LPCTSTR pszMasterIP, int nMasterPort);
	void	ClearPortSet();
	/*/ 向 1 ~ N 广播一个消息。
	void	BROADCAST1(int nPortFrom, int nPacket, int nVarType, const void* buf)
	{
		for(int i = 1; i < m_nPortSize i++)
		{
			if(i != nPortFrom)
				m_setSocket[i].Send(nPort, nPacket, nVarType, buf);
		}
	}//*/

////////////////////////////////////////////////////////////////////////////////////////
// 新接口
public:
	// release by: delete pMessagePort;
	// (szKey==""): need not key
	static IMessagePort* CreateNew(int nPortID, int nPortSize, LPCTSTR szMasterIP, int nMasterPort, LPCTSTR szKey);

////////////////////////////////////////////////////////////////////////////////////////
protected:
	// 服务端(主节点)的IP地址和端口号
	int				m_nPortSize;
	char			m_szMasterIP[IPSTR_SIZE];
	int				m_nMasterPort;
	char			m_szKey[MAX_KEYSIZE];

	typedef	vector<SOCKET> PORT_SET;
	PORT_SET		m_setSocket;				// 0~(size-1)为发送SOCKET表,自己为INVALID_SOCKET。服务端:后面的为刚accept()的SOCKET,还不知道ID的接口。(用于服务端)
	SOCKET			m_sockMain;					// listend()的SOCKET、或者connect()的SOCKET。

	typedef	vector<CRecvBuffer> BUFFER_SET;
	BUFFER_SET		m_setRecvBuf;				// 服务端每个子节点一个BUF,客户端只有1个。

	// 仅用于控制windows Startup & Cleanup
	bool			m_bWinStartup;
};



#endif // INTERNETPORT_H














⌨️ 快捷键说明

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