📄 comm.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 + -