TCPSrv.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #include "stdafx.h"
  2. #include <afxtempl.h>
  3. #include <winsock2.h>
  4. #include <Mswsock.h>
  5. #include <list>
  6. #include <vector>
  7. #include <string>
  8. #include <process.h>
  9. #include <time.h>
  10. #include <map>
  11. #include "iostream"
  12. using namespace std;
  13. #define SOCKET_BUF_SIZE 10240 // 发送、接收缓冲区最大长度,10K
  14. #define OVERLAPPED_DELIVER_SEND 0 // 发送数据
  15. #define OVERLAPPED_DELIVER_RECV 2 // 接收数据
  16. class MyTcpSrv;
  17. // 客户端套接字元
  18. typedef struct _CLIENT_ELEMENT
  19. {
  20. SOCKET s_socket; // 客户端SOCKET套接字
  21. SOCKADDR_IN s_clientInfo; // 客户端终端信息
  22. time_t s_tVisitTM; // 访问时间
  23. bool s_bFirstFrame; // 第一帧标志位
  24. _CLIENT_ELEMENT()
  25. {
  26. s_socket = INVALID_SOCKET;
  27. }
  28. } TS_CLIENT_ELEMENT, * LPTS_CLIENT_ELEMENT;
  29. // 通信载体,此处使用尾随参数的解决思路,故而OVERLAPPED必须为第一个参数
  30. typedef struct _SOCKET_INFORMATION
  31. {
  32. OVERLAPPED s_overlapped;
  33. CHAR s_buffer[SOCKET_BUF_SIZE]; // 存储接收的字符
  34. int s_nBufLen; // 接收的长度
  35. WSABUF s_dataBuf; // 接收缓冲区,为OS自动填充区
  36. LPTS_CLIENT_ELEMENT s_lpClientElement; // 客户端套接字元
  37. UINT s_uDeliverType; // 异步请求类型
  38. int s_uAntiSendSize; // 预期发送字节数
  39. bool s_bIsDiscard; // 作废标志位
  40. MyTcpSrv* s_pThis; // 所有者
  41. _SOCKET_INFORMATION()
  42. {
  43. s_lpClientElement = NULL;
  44. s_pThis = NULL;
  45. }
  46. } SOCKET_INFORMATION, * LPSOCKET_INFORMATION;
  47. // TCPSrv、UDP网络报文数据结构
  48. typedef struct _netPara
  49. {
  50. UCHAR s_szBuf[SOCKET_BUF_SIZE]; // 数据缓存
  51. WORD s_wBufLen; // 数据长度
  52. // 追加字符
  53. void Append(_netPara* pNet)
  54. {
  55. memcpy(s_szBuf + s_wBufLen,pNet->s_szBuf,min(SOCKET_BUF_SIZE - s_wBufLen, pNet->s_wBufLen));
  56. s_wBufLen += pNet->s_wBufLen;
  57. }
  58. // 释放
  59. void Release(UINT uSize)
  60. {
  61. UCHAR szBuf[SOCKET_BUF_SIZE];
  62. memcpy(szBuf, s_szBuf + uSize, s_wBufLen - uSize);
  63. memset(s_szBuf, 0, SOCKET_BUF_SIZE);
  64. memcpy(s_szBuf, szBuf, s_wBufLen - uSize);
  65. s_wBufLen = s_wBufLen - uSize;
  66. }
  67. }SNetPara, * LPNetPara;
  68. // 终端信息结构
  69. typedef struct _terminal_info
  70. {
  71. string s_ip; // IP地址
  72. USHORT s_uPort; // 端口号
  73. // 重载<运算符,以支持作为map的key
  74. friend inline bool operator < (const _terminal_info &ls, const _terminal_info &rs);
  75. friend inline bool operator == (const _terminal_info &ls, const _terminal_info &rs);
  76. }TERMINAL_INFO, * LPTERMINAL_INFO;
  77. // LESS
  78. bool operator < (const _terminal_info& ls, const _terminal_info& rs)
  79. {
  80. return (ls.s_ip < rs.s_ip || (ls.s_ip == rs.s_ip && ls.s_uPort < rs.s_uPort));
  81. }
  82. // EQUAL
  83. bool operator == (const _terminal_info& ls, const _terminal_info& rs)
  84. {
  85. return (ls.s_ip == rs.s_ip && ls.s_uPort == rs.s_uPort);
  86. }
  87. typedef vector<TS_CLIENT_ELEMENT> VClnt; // 客户端信息列表
  88. typedef list<SNetPara> LNetPara; // 接收信息列表
  89. typedef map<TERMINAL_INFO, SNetPara> MNetDatagram; // 网络数据包
  90. // TCP服务器端
  91. class MyTcpSrv
  92. {
  93. private:
  94. CRITICAL_SECTION m_csLock; // 临界对象,冲突锁
  95. HANDLE m_hIOCP; // 完成端口句柄
  96. SOCKADDR_IN m_LocalAddr; // 本地终端地址
  97. SOCKET m_sLinstenSocket; // 侦听套接字
  98. HANDLE m_hListenThread; // 侦听线程
  99. UINT m_nListenThreadId; // 侦听线程ID
  100. HANDLE m_hListenEventExit; // 侦听线程退出事件对象,用于退出侦听线程时通知子线程关闭
  101. SYSTEM_INFO m_sysInfo; // 系统信息,其中包含处理器等信息
  102. VClnt m_clntList; // 客户端清单
  103. MNetDatagram m_netParaMap; // 接收信息列表
  104. public:
  105. MyTcpSrv()
  106. {
  107. InitializeCriticalSection(&m_csLock);
  108. m_hIOCP = INVALID_HANDLE_VALUE;
  109. m_sLinstenSocket = INVALID_SOCKET;
  110. m_hListenThread = INVALID_HANDLE_VALUE;
  111. m_hListenEventExit = INVALID_HANDLE_VALUE;
  112. }
  113. ~MyTcpSrv()
  114. {
  115. DeleteCriticalSection(&m_csLock);
  116. }
  117. private:
  118. // 加载SOCK DLL
  119. bool LoadSock();
  120. // 设置本地终端
  121. bool SetLocalAddr(WORD nPort, const char *szAddr);
  122. // 初始化完成端口
  123. bool InitialIOCP();
  124. // 设置侦听套接字
  125. bool SetupListenSocket();
  126. // 投递接收请求
  127. void DeliverRecv(LPSOCKET_INFORMATION lpInfo);
  128. // 投递发送请求
  129. void DeliverSend(LPSOCKET_INFORMATION lpInfo);
  130. // 启动侦听线程
  131. bool RunListenThread();
  132. // 侦听例程
  133. UINT static WINAPI TCPListenThreadProc(LPVOID pParam);
  134. // 工作例程
  135. UINT static WINAPI ServerWorkerThread(LPVOID CompletionPortID);
  136. // 擦除记录
  137. void Erase(LPSOCKET_INFORMATION lpSocketInfo);
  138. // 解析获取的数据
  139. void OnRecvData(LPSOCKET_INFORMATION lpSocketInfo);
  140. // 停止侦听
  141. void StopListening();
  142. // 断开与指定客户端连接
  143. void DisconnectUser(SOCKADDR_IN clientAddr);
  144. // 断开与所有用户连接
  145. void DisconnectAllUsers();
  146. // 卸载SOCKDLL
  147. void UnloadSock();
  148. public:
  149. // 创建通道
  150. bool Create(LPTERMINAL_INFO pInfo);
  151. // 关闭通道
  152. void Close();
  153. // 读取数据
  154. int Read(byte byRecv[], UINT uMaxSize, LPTERMINAL_INFO pInfo);
  155. // 发送数据
  156. int Write(byte bySend[], UINT uAntiSize, LPTERMINAL_INFO pInfo);
  157. // 重置服务器
  158. bool Reset();
  159. // 获取客户端列表信息
  160. VClnt GetClinetList()
  161. {
  162. return m_clntList;
  163. }
  164. };