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

📄 comm.h

📁 通讯中间件
💻 H
字号:
/*++

版权所有(C),清华深讯公司

模块名:

	comm.h

摘要:

    通信类

作者:

    周辉球

环境:

    Win32平台和LINUX平台

修改历史:


--*/

#ifndef _COMM_H_
#define _COMM_H_

#ifdef _WIN32

#include <stdlib.h>
#include <stdio.h>
#include <winsock2.h> 
#include <memory.h>
#include <string.h>
#include <time.h>
#include <iostream>
#include <process.h>
#include <windows.h>
#include <winbase.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
	
#pragma comment(lib, "ws2_32.lib")

#ifndef socklen_t
#define socklen_t int
#endif

#else

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <pthread.h>
#include <signal.h>
#include <iconv.h>
#include <stdarg.h>
#include <errno.h>

#ifndef SOCKET
#define SOCKET int
#define INVALID_SOCKET  (SOCKET)(~0)
#define SOCKET_ERROR            (-1)
#define closesocket   close
#endif

#ifndef HANDLE 
#define HANDLE pthread_t
#endif

#ifndef DWORD
#define DWORD unsigned long
#endif

#ifndef NULL
#define NULL 0
#endif

#ifndef CRITICAL_SECTION
#define CRITICAL_SECTION pthread_mutex_t
#define InitializeCriticalSection(x) pthread_mutex_init(x, NULL)
#define DeleteCriticalSection(x) pthread_mutex_destroy(x)
#define EnterCriticalSection(x) pthread_mutex_lock(x)
#define LeaveCriticalSection(x) pthread_mutex_unlock(x)
#endif

#ifndef MAX_PATH
#define MAX_PATH			256
#endif

#ifndef _snprintf
#define _snprintf snprintf
#endif

#endif

class TLogFile;
extern TLogFile g_CommLog;

//////////////////////////////////////////////////////////
// 宏定义(开始)
#ifndef _DEFINE_
#define _DEFINE_

// 消息类型定义
#define COMM_AUTH						0x00000001      // 认证消息
#define COMM_DATA                       0x00000002      // 数据消息

// 函数返回值错误码
#define COMM_ERR_NONE			        0x00000000		// 调用成功,正常返回
#define COMM_ERR_CREATETHREAD			0x00000001		// 创建线程失败
#define COMM_ERR_TOOMANGSESSION			0x00000002		// 创建的线程太多已达到系统上限
#define COMM_ERR_INITLOCK				0x00000003		// 初始化锁出错
#define COMM_ERR_DESTROYLOCK			0x00000004		// 清除锁出错
#define COMM_ERR_LOCK				    0x00000005		// 加锁出错
#define COMM_ERR_UNLOCK				    0x00000006		// 解锁出错
#define COMM_ERR_PARAM					0x00000007		// 传入参数错误
#define COMM_ERR_TOOMANYLINK		    0x00000008		// 连接太多
#define COMM_ERR_TOOMANYTHREAD		    0x00000009		// 线程太多
#define COMM_ERR_NOLINK		            0x0000000A		// 没有该连接
#define COMM_ERR_NOTHREAD		        0x0000000B		// 没有该线程
#define COMM_ERR_MEMORY		            0x0000000C		// 内寸分配失败
#define COMM_ERR_NOMODULE		        0x0000000D		// 没有该模块
#define COMM_ERR_NOTRUSTIP		        0x0000000E		// 没有该信任地址
#define COMM_ERR_WAITSEND		        0x0000000F		// 放入缓冲区等待重发
#define COMM_ERR_WAITEMPTY		        0x00000010		// 重发缓冲队列空
#define COMM_ERR_WAITFULL		        0x00000011		// 重发缓冲队列满
#define COMM_ERR_TOOMANYLISTEN		    0x00000012		// 监听太多
#define COMM_ERR_UNKNOWN				0xFFFFFFFF		// 错误原因不祥

#define COMM_PDU_SIZE 8208								// 消息包最大长度
#define COMM_BODY_SIZE 8192								// 消息体最大长度
#define COMM_PDU_RECV (COMM_PDU_SIZE * 5)				// 每次允许收取消息的最大长度
#define COMM_LINK_MAX 250								// 最大连接个数(包括出连接和入连接)
#define COMM_LISTEN_MAX 1								// 最大监听个数
#define COMM_TRUSTIP_MAX 256							// 信任的外部IP个数最大值
#define COMM_WAITSEND_MAX 100							// 等待重发的最大个数
#define COMM_WAITSEND_NUM 10							// 每个重发线程缓存的消息包数量

#endif // _DEFINE_
// 宏定义(结束)
//////////////////////////////////////////////////////////







//////////////////////////////////////////////////////////
// 消息包类(开始)
#ifndef _PACKET_
#define _PACKET_

class TPacket
{
public:
	TPacket() {};
    virtual ~TPacket(void) {};

public:
	unsigned long m_ModuleID;
	unsigned long m_BodyLen;
	char m_BodyBuf[COMM_BODY_SIZE + 8];
};

#endif // _PACKET_
// 消息包类(结束)
//////////////////////////////////////////////////////////







//////////////////////////////////////////////////////////
// 互斥类(开始)
#ifndef _MUTEX_
#define _MUTEX_

class TMutex
{
public:
	TMutex() {InitializeCriticalSection(&m_cs);};
    virtual ~TMutex(void) {DeleteCriticalSection(&m_cs);};

	// 加锁
	void Lock() {EnterCriticalSection(&m_cs);};

	// 解锁
    void UnLock() {LeaveCriticalSection(&m_cs);};

private:
	CRITICAL_SECTION m_cs;
};

#endif // _MUTEX_
// 互斥类(结束)
//////////////////////////////////////////////////////////








//////////////////////////////////////////////////////////
// 连接模块类(开始)
#ifndef _LINK_
#define _LINK_

class TLink
{
public:
	TLink()
	{
		m_Assigned = 0;

		m_SocketID = INVALID_SOCKET;
		m_ModuleID = 0;
		m_ConnectType = 0;
		m_ConnectTime = 0;
		m_RecvTime = 0;
		m_SendTime = 0;
		m_ForeignPort = 0;
		m_LocalPort = 0;
		memset(m_ForeignIP, 0, sizeof(m_ForeignIP));
		memset(m_LocalIP, 0, sizeof(m_LocalIP));
	};

	virtual ~TLink(void) 
	{
		if (m_SocketID != INVALID_SOCKET)
		{
			closesocket(m_SocketID);
			m_SocketID = INVALID_SOCKET;
		}
	};

	// 被使用
	void Assign() 
	{
		m_Assigned = 1;

		m_SocketID = INVALID_SOCKET;
		m_ModuleID = 0;
		m_ConnectType = 0;
		m_ConnectTime = 0;
		m_RecvTime = 0;
		m_SendTime = 0;
		m_ForeignPort = 0;
		m_LocalPort = 0;
		memset(m_ForeignIP, 0, sizeof(m_ForeignIP));
		memset(m_LocalIP, 0, sizeof(m_LocalIP));
	};

	// 释放
	void Release() 
	{
		if (m_SocketID != INVALID_SOCKET)
		{
			closesocket(m_SocketID);
		}
		m_SocketID = INVALID_SOCKET;
		m_ModuleID = 0;
		m_ConnectType = 0;
		m_ConnectTime = 0;
		m_RecvTime = 0;
		m_SendTime = 0;
		m_ForeignPort = 0;
		m_LocalPort = 0;
		memset(m_ForeignIP, 0, sizeof(m_ForeignIP));
		memset(m_LocalIP, 0, sizeof(m_LocalIP));

		m_Assigned = 0;
	};

	// 断开连接
	void Close() 
	{
		if (m_SocketID != INVALID_SOCKET)
		{
			closesocket(m_SocketID);
		}
		m_SocketID = INVALID_SOCKET;
		m_ModuleID = 0;
		m_ConnectType = 0;
		m_ConnectTime = 0;
		m_RecvTime = 0;
		m_SendTime = 0;
		m_ForeignPort = 0;
		m_LocalPort = 0;
		memset(m_ForeignIP, 0, sizeof(m_ForeignIP));
		memset(m_LocalIP, 0, sizeof(m_LocalIP));
	};

	// 占用状态
	int Status() 
	{
		if (m_Assigned == 0)
			return 0;

		return 1;
	};

public:
	SOCKET m_SocketID;						// 连接描述字
	unsigned long m_ModuleID;				// 该连接的对方模块ID
	int m_ConnectType;						// 该连接的类型, 1:客户端(主动连接服务器),2:服务器端(被动接收客户连接),其它:没有连接
	time_t m_ConnectTime;					// 连接建立时间的流逝秒数表示
	time_t m_RecvTime;						// 最后收到有效数据时间的流逝秒数表示
	time_t m_SendTime;						// 最后发送有效数据时间的流逝秒数表示
	char m_ForeignIP[32];					// 对方IP地址
	unsigned short m_ForeignPort;			// 对方连接端口
	char m_LocalIP[32];						// 本地IP地址
	unsigned short m_LocalPort;				// 本地连接端口

private:
	int m_Assigned;							// 被使用标志,0:未用,非0:已用
};

#endif // _LINK_
// 连接模块类(结束)
//////////////////////////////////////////////////////////










//////////////////////////////////////////////////////////
// 监听模块类(开始)
#ifndef _LISTEN_
#define _LISTEN_

class TListen
{
public:
	TListen()
	{
		m_ListenPort = 0;
		m_ListenSocket = INVALID_SOCKET;
		m_ListenTime = 0;
	};

	virtual ~TListen(void) 
	{
		if (m_ListenSocket != INVALID_SOCKET)
		{
			closesocket(m_ListenSocket);
			m_ListenSocket = INVALID_SOCKET;
		}
	};

public:
	unsigned short m_ListenPort;			// 监听端口
	SOCKET m_ListenSocket;					// 监听描述字
	time_t m_ListenTime;					// 连接建立时间的流逝秒数表示
};

#endif // _LISTEN_
// 监听模块类(结束)
//////////////////////////////////////////////////////////










//////////////////////////////////////////////////////////
// 日志文件类(开始)
#ifndef _LOGFILE_
#define _LOGFILE_

class TLogFile
{
public:
	TLogFile()
	{
		memset(m_szLogFile, 0, sizeof(m_szLogFile));
		strncpy(m_szLogFile, "comm.log", sizeof(m_szLogFile) - 1);
		
		m_nMaxBytes = 8 * 1024 * 1024;

		m_FP = NULL;
	}

    virtual ~TLogFile(void) 
	{
		if (m_FP != NULL)
		{
			fclose(m_FP);
			m_FP = NULL;
		}
	}

	// 设置日志文件名
	void SetFileName(const char *lpszFileName) 
	{
		if (lpszFileName != NULL)
		{
			memset(m_szLogFile, 0 , sizeof(m_szLogFile));
			strncpy(m_szLogFile, lpszFileName, sizeof(m_szLogFile) - 1);
		}

		return;
	}

	// 设置日志文件大小上限
	void SetMaxBytes(int nMaxBytes) 
	{
		if (nMaxBytes >= 1024)
		{
			m_nMaxBytes = nMaxBytes;
		}

		return;
	}


	// 得到日志文件名
	char *GetFileName() {return m_szLogFile;};

	// 得到日志文件大小上限
	int GetMaxBytes() {return m_nMaxBytes;};

	// 记录日志到日志文件
	void Print(const char *format, ...) 
	{
		if (format == NULL)
			return;

		char logtime[30];
		time_t now;
		
		// 得到当前时间
		now = time(NULL);
		memset(logtime, 0, sizeof(logtime));
		_snprintf(logtime, sizeof(logtime) - 1, "%04d-%02d-%02d %02d:%02d:%02d     ", 
				localtime(&now)->tm_year + 1900,  
				localtime(&now)->tm_mon + 1, 
				localtime(&now)->tm_mday, 
				localtime(&now)->tm_hour, 
				localtime(&now)->tm_min, 
				localtime(&now)->tm_sec);

		m_Lock.Lock();

		// 未关闭则先关闭
		if (m_FP != NULL)
		{
			fclose(m_FP);
			m_FP = NULL;
		}

		// 超过最大限制则删除
#ifdef _WIN32
		struct _stat stbuf;
		int result;

		result = _stat(m_szLogFile, &stbuf);
		if (result == 0)
		{
			if (stbuf.st_size >= m_nMaxBytes)
			{
				remove(m_szLogFile);
			}
		}
#else
		struct stat stbuf;
		int result;

		result = stat(m_szLogFile, &stbuf );
		if (result == 0)
		{
			if (stbuf.st_size >= m_nMaxBytes)
			{
				remove(m_szLogFile);
			}
		}
#endif

		// 写数据到文件
		m_FP = fopen(m_szLogFile, "a+");
		if (m_FP != NULL)
		{
			fprintf(m_FP, "\n%s", logtime);

			va_list ap;
			va_start(ap, format);
			vfprintf(m_FP, format, ap);
			va_end(ap);

			fflush(m_FP);		
			fclose(m_FP);
			m_FP = NULL;
		}

		m_Lock.UnLock();

		return;
	}

private:
	FILE *m_FP;
	char m_szLogFile[MAX_PATH];
	int m_nMaxBytes;

	TMutex m_Lock;
};

#endif // _LOGFILE_
// 日志文件类(结束)
//////////////////////////////////////////////////////////








//////////////////////////////////////////////////////////
// 通信类(开始)
#ifndef _COMM_
#define _COMM_

class TComm
{
public:
	TComm();
    virtual ~TComm(void);

	// 设置模块标识
	int SetModuleID(unsigned long uModuleID) 
	{
		if (uModuleID == 0)
		{
			return COMM_ERR_PARAM;
		}

		m_ModuleID = uModuleID;

		return COMM_ERR_NONE;
	};

	// 增加服务器端
	int AddServer(unsigned short uListenPort);

	// 增加客户端
	int AddClient(const char *szHost, unsigned short uPort);

	// 发送消息包
	int SendMessage(const TPacket *lpPacket);

	// 连接服务器
	SOCKET Connect(const char *host, unsigned short port);

	// 监听在指定端口
	SOCKET Listen(unsigned short port);

	// 发送原始数据到指定连接
	int Send(SOCKET s, void *buf, int len, int flags);

	// 消息包事件处理函数
	void OnReceive(const TPacket *lpPacket);

	// 连接注册事件处理函数
	void OnConnect(const TPacket *lpPacket);

	// 连接关闭事件处理函数
	void OnClose(const TPacket *lpPacket);

	// 分配一个LINK位置
	TLink * AssignLink();

	// 增加信任的外部连接
	void AddTrustIP(const char *ip);

	// 删除信任的外部连接
	void DelTrustIP(const char *ip);

	// 是否在允许的外部连接IP范围内
	int AllowIP(const char *ip);

	// 得到模块标识
	unsigned long GetModuleID() {return m_ModuleID;};

	// 增加线程个数
	void AddThreadCount() 
	{
		m_Lock.Lock();
		m_ThreadCount++;
		m_Lock.UnLock();
	};

	// 减少线程个数
	void DelThreadCount() 
	{
		m_Lock.Lock();
		m_ThreadCount--;
		m_Lock.UnLock();
	};

	// 是否存在指定的模块
	int ExistID(unsigned long uID);

	// 加锁
	void Lock() {m_Lock.Lock();};

	// 解锁
	void UnLock() {m_Lock.UnLock();};

	// 取出重发消息包
	int GetPacket(TPacket *lpPacket);

	// 放进重发消息包
	int PutPacket(const TPacket *lpPacket);

protected:

private:


public:
	TLink m_Link[COMM_LINK_MAX];
	TListen m_Listen[COMM_LISTEN_MAX];
	int m_Stoped;
	
protected:

private:
	TMutex m_Lock;
	unsigned long m_ModuleID;
	int m_ThreadCount;
	unsigned long m_TrustIP[COMM_TRUSTIP_MAX];

	int m_WaitSendGetPos;
	int m_WaitSendPutPos;
	TPacket m_WaitSendPacket[COMM_WAITSEND_MAX];
};

#endif // _COMM_
// 通信类(结束)
//////////////////////////////////////////////////////////

#endif // _COMM_H_

⌨️ 快捷键说明

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