#include "stdafx.h" #include #include #include #include #include #include #include #include #include #include "iostream" using namespace std; #define SOCKET_BUF_SIZE 10240 // 发送、接收缓冲区最大长度,10K #define OVERLAPPED_DELIVER_SEND 0 // 发送数据 #define OVERLAPPED_DELIVER_RECV 2 // 接收数据 class MyTcpSrv; // 客户端套接字元 typedef struct _CLIENT_ELEMENT { SOCKET s_socket; // 客户端SOCKET套接字 SOCKADDR_IN s_clientInfo; // 客户端终端信息 time_t s_tVisitTM; // 访问时间 bool s_bFirstFrame; // 第一帧标志位 _CLIENT_ELEMENT() { s_socket = INVALID_SOCKET; } } TS_CLIENT_ELEMENT, * LPTS_CLIENT_ELEMENT; // 通信载体,此处使用尾随参数的解决思路,故而OVERLAPPED必须为第一个参数 typedef struct _SOCKET_INFORMATION { OVERLAPPED s_overlapped; CHAR s_buffer[SOCKET_BUF_SIZE]; // 存储接收的字符 int s_nBufLen; // 接收的长度 WSABUF s_dataBuf; // 接收缓冲区,为OS自动填充区 LPTS_CLIENT_ELEMENT s_lpClientElement; // 客户端套接字元 UINT s_uDeliverType; // 异步请求类型 int s_uAntiSendSize; // 预期发送字节数 bool s_bIsDiscard; // 作废标志位 MyTcpSrv* s_pThis; // 所有者 _SOCKET_INFORMATION() { s_lpClientElement = NULL; s_pThis = NULL; } } SOCKET_INFORMATION, * LPSOCKET_INFORMATION; // TCPSrv、UDP网络报文数据结构 typedef struct _netPara { UCHAR s_szBuf[SOCKET_BUF_SIZE]; // 数据缓存 WORD s_wBufLen; // 数据长度 // 追加字符 void Append(_netPara* pNet) { memcpy(s_szBuf + s_wBufLen,pNet->s_szBuf,min(SOCKET_BUF_SIZE - s_wBufLen, pNet->s_wBufLen)); s_wBufLen += pNet->s_wBufLen; } // 释放 void Release(UINT uSize) { UCHAR szBuf[SOCKET_BUF_SIZE]; memcpy(szBuf, s_szBuf + uSize, s_wBufLen - uSize); memset(s_szBuf, 0, SOCKET_BUF_SIZE); memcpy(s_szBuf, szBuf, s_wBufLen - uSize); s_wBufLen = s_wBufLen - uSize; } }SNetPara, * LPNetPara; // 终端信息结构 typedef struct _terminal_info { string s_ip; // IP地址 USHORT s_uPort; // 端口号 // 重载<运算符,以支持作为map的key friend inline bool operator < (const _terminal_info &ls, const _terminal_info &rs); friend inline bool operator == (const _terminal_info &ls, const _terminal_info &rs); }TERMINAL_INFO, * LPTERMINAL_INFO; // LESS bool operator < (const _terminal_info& ls, const _terminal_info& rs) { return (ls.s_ip < rs.s_ip || (ls.s_ip == rs.s_ip && ls.s_uPort < rs.s_uPort)); } // EQUAL bool operator == (const _terminal_info& ls, const _terminal_info& rs) { return (ls.s_ip == rs.s_ip && ls.s_uPort == rs.s_uPort); } typedef vector VClnt; // 客户端信息列表 typedef list LNetPara; // 接收信息列表 typedef map MNetDatagram; // 网络数据包 // TCP服务器端 class MyTcpSrv { private: CRITICAL_SECTION m_csLock; // 临界对象,冲突锁 HANDLE m_hIOCP; // 完成端口句柄 SOCKADDR_IN m_LocalAddr; // 本地终端地址 SOCKET m_sLinstenSocket; // 侦听套接字 HANDLE m_hListenThread; // 侦听线程 UINT m_nListenThreadId; // 侦听线程ID HANDLE m_hListenEventExit; // 侦听线程退出事件对象,用于退出侦听线程时通知子线程关闭 SYSTEM_INFO m_sysInfo; // 系统信息,其中包含处理器等信息 VClnt m_clntList; // 客户端清单 MNetDatagram m_netParaMap; // 接收信息列表 public: MyTcpSrv() { InitializeCriticalSection(&m_csLock); m_hIOCP = INVALID_HANDLE_VALUE; m_sLinstenSocket = INVALID_SOCKET; m_hListenThread = INVALID_HANDLE_VALUE; m_hListenEventExit = INVALID_HANDLE_VALUE; } ~MyTcpSrv() { DeleteCriticalSection(&m_csLock); } private: // 加载SOCK DLL bool LoadSock(); // 设置本地终端 bool SetLocalAddr(WORD nPort, const char *szAddr); // 初始化完成端口 bool InitialIOCP(); // 设置侦听套接字 bool SetupListenSocket(); // 投递接收请求 void DeliverRecv(LPSOCKET_INFORMATION lpInfo); // 投递发送请求 void DeliverSend(LPSOCKET_INFORMATION lpInfo); // 启动侦听线程 bool RunListenThread(); // 侦听例程 UINT static WINAPI TCPListenThreadProc(LPVOID pParam); // 工作例程 UINT static WINAPI ServerWorkerThread(LPVOID CompletionPortID); // 擦除记录 void Erase(LPSOCKET_INFORMATION lpSocketInfo); // 解析获取的数据 void OnRecvData(LPSOCKET_INFORMATION lpSocketInfo); // 停止侦听 void StopListening(); // 断开与指定客户端连接 void DisconnectUser(SOCKADDR_IN clientAddr); // 断开与所有用户连接 void DisconnectAllUsers(); // 卸载SOCKDLL void UnloadSock(); public: // 创建通道 bool Create(LPTERMINAL_INFO pInfo); // 关闭通道 void Close(); // 读取数据 int Read(byte byRecv[], UINT uMaxSize, LPTERMINAL_INFO pInfo); // 发送数据 int Write(byte bySend[], UINT uAntiSize, LPTERMINAL_INFO pInfo); // 重置服务器 bool Reset(); // 获取客户端列表信息 VClnt GetClinetList() { return m_clntList; } };