global.h
上传用户:chinaliu11
上传日期:2022-03-10
资源大小:11842k
文件大小:11k
源码类别:

P2P编程

开发平台:

Visual C++

  1. /* Filename : global.h */
  2. #ifndef GLOBAL_H
  3. #define GLOBAL_H
  4. #ifndef DLL_INTERNAL
  5. #define DLL_INTERNAL __declspec( dllexport )
  6. #endif
  7. //==========================================================================
  8. // 常用操作宏
  9. //==========================================================================
  10. #define GET_VALID_STRING_FROM_TOW(cs1,cs2) ( (cs1.GetLength()>0)?cs1:cs2 )
  11. #define GET_SAFE_STRING(str) ( (str)?(str):"" )
  12. #define NULL_STRING_FOR_DB ""
  13. #define GET_VALID_CSTRING(cs) ( (cs).GetLength()>0?(cs):((cs),(cs)=NULL_STRING_FOR_DB) )
  14. #define GET_VALID_CSTRING_P(csp) ( (csp)?(*(csp)):"" )
  15. #define STRNCPY_CS(sz,cs) strncpy((char*)(sz),(cs).GetBuffer(0),sizeof(sz)-1)
  16. #define STRNCPY_SZ(sz1,sz2) strncpy(((char*)(sz1)),(sz2)?((char*)(sz2)):"",sizeof(sz1)-1)
  17. #define STRNCPY(sz1,sz2,size) 
  18. {
  19. strncpy(((char*)(sz1)),(sz2)?((char*)(sz2)):"",(size));
  20. ((char*)(sz1))[(size)-1] = '';
  21. }
  22. #define STRCPY(sz1,sz2) strcpy ( (char*)(sz1), (char*)((sz2)?(sz2):"") )
  23. #define STRLEN_SZ(sz) ((sz)?strlen((char*)(sz)):0)
  24. #define COPMNC_CS_SZ(cs,sz) ( (sz) && ((cs).CompareNoCase(sz)==0) )
  25. #define STRCMP_SAFE(sz1,sz2) (strcmp((char*)GET_SAFE_STRING(sz1),(char*)GET_SAFE_STRING(sz2)))
  26. #define STRLEN_SAFE(sz) ((sz)?strlen((char*)(sz)):0)
  27. #define ATOI_SAFE(sz) (atoi((const char*)(GET_SAFE_STRING((char*)(sz)))))
  28. #define ASSERT_ADDRESS(p,size) ASSERT((p)!=NULL && AfxIsValidAddress((p),(size),TRUE))
  29. #define VALID_IP_PORT(ip,port) ((STRLEN_SAFE(ip)>0) && (port)>1000)
  30. // 开关标志是否“置位”了
  31. #define SWITCH_IS_FLAG(nConstFlag,nValue) ( ( (nConstFlag) & (nValue) ) == (nConstFlag) )
  32. #define LENGTH(x) sizeof(x)/sizeof(x[0])
  33. #define MIN(x,y) (((DWORD)(x)<(DWORD)(y))?(x):(y))
  34. #define MAX(x,y) (((DWORD)(x)>(DWORD)(y))?(x):(y))
  35. // 句柄是否有效
  36. #define HANDLE_IS_VALID(h) ( HANDLE(h) && HANDLE(h) != INVALID_HANDLE_VALUE )
  37. // 关闭句柄
  38. #define SAFE_CLOSE_HANDLE(h)
  39. {
  40. if ( HANDLE_IS_VALID ( h ) )
  41. {
  42. CloseHandle ( h );
  43. h = NULL;
  44. }
  45. }
  46. // 等待事件的 Sleep() 函数
  47. #define SLEEP_RETURN(x)
  48. {
  49. if ( ::WaitForSingleObject ( m_hEvtEndModule, x ) == WAIT_OBJECT_0 )
  50. return FALSE;
  51. }
  52. #define SLEEP_BREAK(x)
  53. {
  54. if ( ::WaitForSingleObject ( m_hEvtEndModule, x ) == WAIT_OBJECT_0 )
  55. break;
  56. }
  57. // 删除一个数组指针
  58. #define DELETE_ARRAY(pp)
  59. {
  60. if ( (pp) && (*(pp)) )
  61. {
  62. (*(pp))->RemoveAll();
  63. (*(pp))->FreeExtra();
  64. delete (*(pp));
  65. (*(pp)) = NULL;
  66. }
  67. }
  68. // 删除所有由 new 申请的内存空间,可以是对象,也可以是普通的数据类型,如int、char等
  69. #define DELETE_HEAP(pp)
  70. {
  71. if ( (pp) && (*(pp)) )
  72. {
  73. delete (*(pp));
  74. (*(pp)) = NULL;
  75. }
  76. }
  77. // 删除所有由 new 申请的数组内存空间,可以是对象,也可以是普通的数据类型,如int、char等
  78. #define DELETE_ARY_HEAP(pp)
  79. {
  80. if ( (pp) && (*(pp)) )
  81. {
  82. delete[] (*(pp));
  83. (*(pp)) = NULL;
  84. }
  85. }
  86. // 用 new 申请一个 基本类型(如:char、int等)或结构体的内存空间,但不能是对象
  87. // 如指针指向有效的空间就将那个空间清零
  88. #define ALLOC_MEM(pp,size,type,desc)
  89. {
  90. if ( (pp) )
  91. {
  92. if ( !(*(pp)) )
  93. {
  94. (*(pp)) = new type[(size)];
  95. if ( !(*(pp)) )
  96. return OutNewObjectFailed ( desc );
  97. }
  98. ASSERT_ADDRESS ( (*(pp)), (size)*sizeof(type) );
  99. memset ( (*(pp)), 0, (size)*sizeof(type) );
  100. }
  101. }
  102. //
  103. template<class T>
  104. int FindFromStaticArray ( IN T *pAry, IN int nArySize, IN T Find )
  105. {
  106. if ( !pAry ) return -1;
  107. for ( int i=0; i<nArySize; i++ )
  108. {
  109. if ( pAry[i] == Find )
  110. return i;
  111. }
  112. return -1;
  113. }
  114. //
  115. // 注意:如果是从 CString 中查找时 Find 千万不要用 LPCTSTR 或者 char* 变量,一定是要用 CString 变量
  116. //
  117. template<class T1, class T2>
  118. int FindFromArray ( IN T1 &Ary, IN T2 Find )
  119. {
  120. int nCount = Ary.GetSize();
  121. for ( int i=0; i<nCount; i++ )
  122. {
  123. T2 tGetValue = Ary.GetAt(i);
  124. if ( tGetValue == Find )
  125. return i;
  126. }
  127. return -1;
  128. }
  129. //
  130. // 从数组 Ary_Org 中查找,只要 Ary_Find 中任何一个元素在 Ary_Org 中出现过
  131. // 就返回该元素在 Ary_Org 中的位置
  132. //
  133. template<class T1, class T2>
  134. int FindFromArray ( IN T1 &Ary_Org, IN T1 &Ary_Find, OUT T2 &Element )
  135. {
  136. int nCount = Ary_Find.GetSize();
  137. for ( int i=0; i<nCount; i++ )
  138. {
  139. T2 tGetValue = Ary_Find.GetAt(i);
  140. int nFindPos = FindFromArray ( Ary_Org, tGetValue );
  141. if ( nFindPos >= 0 )
  142. {
  143. Element = Ary_Org.GetAt ( nFindPos );
  144. return nFindPos;
  145. }
  146. }
  147. return -1;
  148. }
  149. template<class T1, class T2, class T3, class T4>
  150. int FindFromArray ( IN T1 &Ary, IN T2 Find, IN T3 &AppAry, IN T4 AppFind )
  151. {
  152. int nCount = Ary.GetSize();
  153. for ( int i=0; i<nCount; i++ )
  154. {
  155. if ( Ary.GetAt(i) == Find && 
  156. AppAry.GetAt(i) == AppFind )
  157. {
  158. return i;
  159. }
  160. }
  161. return -1;
  162. }
  163. template<class T1>
  164. int FindFromArray ( IN T1 &Ary_Src, IN T1 &Ary_Find )
  165. {
  166. int nCount = Ary_Src.GetSize();
  167. for ( int i=0; i<nCount; i++ )
  168. {
  169. if ( FindFromArray ( Ary_Find, Ary_Src.GetAt(i) ) >= 0 )
  170. return i;
  171. }
  172. return -1;
  173. }
  174. //
  175. // 将数组 Ary_Src 中的元素拷贝到 Ary_Dest 中
  176. //
  177. template<class T>
  178. int ArrayCopy ( IN T &Ary_Dest, IN T &Ary_Src )
  179. {
  180. int nCount = Ary_Src.GetSize();
  181. for ( int i=0; i<nCount; i++ )
  182. {
  183. Ary_Dest.Add ( Ary_Src.GetAt(i) );
  184. }
  185. return i;
  186. }
  187. //
  188. // 将数组 Ary_Src 中的元素拷贝到 Ary_Dest 中,并保证 Ary_Src 中的元素不会重复拷贝
  189. //
  190. template<class T>
  191. int ArrayCopy_DefferValue ( IN T &Ary_Dest, IN T &Ary_Src )
  192. {
  193. int nCount = Ary_Src.GetSize();
  194. for ( int i=0; i<nCount; i++ )
  195. {
  196. if ( FindFromArray ( Ary_Dest, Ary_Src.GetAt(i) ) < 0 )
  197. Ary_Dest.Add ( Ary_Src.GetAt(i) );
  198. }
  199. return i;
  200. }
  201. //
  202. // 将数组 Ary 中的元素次序颠倒,T2 是 Ary 里保存的数据类型
  203. //
  204. template<class T1, class T2>
  205. void ReversalArray ( IN T1 &Ary, T2 &Temp )
  206. {
  207. for ( int i=0; i<Ary.GetSize()/2; i++ )
  208. {
  209. Temp = Ary.GetAt(i);
  210. Ary.SetAt ( i, Ary.GetAt(Ary.GetSize()-1-i) );
  211. Ary.SetAt ( Ary.GetSize()-1-i, Temp );
  212. }
  213. }
  214. /*
  215. 《TCP实现P2P通信、TCP穿越NAT的方法、TCP打洞》
  216. 这里假设公网上的服务器S,客户端A在NAT-A后面,客户端B在NAT-B后面,现在客户端A希望和客户端B建立直接的
  217. TCP 连接,客户端A为主动端,客户端B为被动端,客户端B向客户端B进行TCP打洞,打洞成功后客户端A便可以直接与
  218. 客户端B建立TCP连接。
  219. */
  220. // 服务器地址和端口号定义
  221. #define SRV_TCP_MAIN_PORT 4000 // 服务器主连接的端口号
  222. #define SRV_TCP_HOLE_PORT 8000 // 服务器响应客户端打洞申请的端口号
  223. #define NET_BUFFER_SIZE 1024 // 缓冲大小
  224. // 数据包类型
  225. typedef enum _packet_type
  226. {
  227. PACKET_TYPE_INVALID,
  228. PACKET_TYPE_NEW_USER_LOGIN, // 服务器收到新的客户端登录,将登录信息发送给其他客户端
  229. PACKET_TYPE_WELCOME, // 客户端登录时服务器发送该欢迎信息给客户端,以告知客户端登录成功
  230. PACKET_TYPE_REQUEST_CONN_CLIENT, // 某客户端向服务器申请,要求与另一个客户端建立直接的TCP连接,即需要进行TCP打洞
  231. PACKET_TYPE_REQUEST_MAKE_HOLE, // 服务器请求某客户端向另一客户端进行TCP打洞,即向另一客户端指定的外部IP和端口号进行connect尝试
  232. PACKET_TYPE_REQUEST_DISCONNECT, // 请求服务器断开连接
  233. PACKET_TYPE_TCP_DIRECT_CONNECT, // 服务器要求主动端(客户端A)直接连接被动端(客户端B)的外部IP和端口号
  234. PACKET_TYPE_HOLE_LISTEN_READY, // 被动端(客户端B)打洞和侦听均已准备就绪
  235. } PACKET_TYPE;
  236. //
  237. // 新用户登录数据
  238. //
  239. typedef struct _new_user_login
  240. {
  241. _new_user_login ()
  242. : ePacketType ( PACKET_TYPE_NEW_USER_LOGIN )
  243. , nClientPort ( 0 )
  244. , dwID ( 0 )
  245. {
  246. memset ( szClientIP, 0, sizeof(szClientIP) );
  247. }
  248. PACKET_TYPE ePacketType; // 包类型
  249. char szClientIP[32]; // 新登录的客户端(客户端B)外部IP地址
  250. UINT nClientPort; // 新登录的客户端(客户端B)外部端口号
  251. DWORD dwID; // 新登录的客户端(客户端B)的ID号(从1开始编号的一个唯一序号)
  252. } t_NewUserLoginPkt;
  253. //
  254. // 欢迎信息
  255. //
  256. typedef struct _welcome
  257. {
  258. _welcome ()
  259. : ePacketType ( PACKET_TYPE_WELCOME )
  260. , nClientPort ( 0 )
  261. , dwID ( 0 )
  262. {
  263. memset ( szClientIP, 0, sizeof(szClientIP) );
  264. memset ( szWelcomeInfo, 0, sizeof(szWelcomeInfo) );
  265. }
  266. PACKET_TYPE ePacketType; // 包类型
  267. char szClientIP[32]; // 接收欢迎信息的客户端外部IP地址
  268. UINT nClientPort; // 接收欢迎信息的客户端外部端口号
  269. DWORD dwID; // 接收欢迎信息的客户端的ID号(从1开始编号的一个唯一序号)
  270. char szWelcomeInfo[64]; // 欢迎信息文本
  271. } t_WelcomePkt;
  272. //
  273. // 客户端A请求服务器协助连接客户端B
  274. //
  275. typedef struct _req_conn_client
  276. {
  277. _req_conn_client ()
  278. : ePacketType ( PACKET_TYPE_REQUEST_CONN_CLIENT )
  279. , dwInviterID ( 0 )
  280. , dwInvitedID ( 0 )
  281. {
  282. }
  283. PACKET_TYPE ePacketType; // 包类型
  284. DWORD dwInviterID; // 发出邀请方(主动方即客户端A)ID号
  285. DWORD dwInvitedID; // 被邀请方(被动方即客户端B)ID号
  286. } t_ReqConnClientPkt;
  287. //
  288. // 服务器请求客户端B打洞
  289. //
  290. typedef struct _srv_req_make_hole
  291. {
  292. _srv_req_make_hole ()
  293. : ePacketType ( PACKET_TYPE_REQUEST_MAKE_HOLE )
  294. , dwInviterID ( 0 )
  295. , dwInvitedID ( 0 )
  296. , dwInviterHoleID ( 0 )
  297. , nClientHolePort ( 0 )
  298. {
  299. memset ( szClientHoleIP, 0, sizeof(szClientHoleIP) );
  300. }
  301. PACKET_TYPE ePacketType; // 包类型
  302. DWORD dwInviterID; // 发出邀请方(主动方即客户端A)ID号
  303. DWORD dwInviterHoleID; // 发出邀请方(主动方即客户端A)打洞ID号
  304. DWORD dwInvitedID; // 被邀请方(被动方即客户端B)ID号
  305. char szClientHoleIP[32]; // 可以向该IP(请求方的外部IP)地址打洞,即发生一次connect尝试
  306. UINT nClientHolePort; // 可以向该端口号(请求方的外部端口号)打洞,即发生一次connect尝试
  307. } t_SrvReqMakeHolePkt;
  308. //
  309. // 请求服务器断开连接
  310. //
  311. typedef struct _req_srv_disconnect
  312. {
  313. _req_srv_disconnect ()
  314. : ePacketType ( PACKET_TYPE_REQUEST_DISCONNECT )
  315. , dwInviterID ( 0 )
  316. , dwInviterHoleID ( 0 )
  317. , dwInvitedID ( 0 )
  318. {
  319. }
  320. PACKET_TYPE ePacketType; // 包类型
  321. DWORD dwInviterID; // 发出邀请方(主动方即客户端A)ID号
  322. DWORD dwInviterHoleID; // 发出邀请方(主动方即客户端A)打洞ID号
  323. DWORD dwInvitedID; // 被邀请方(被动方即客户端B)ID号
  324. } t_ReqSrvDisconnectPkt;
  325. //
  326. // 服务器要求主动端(客户端A)直接连接被动端(客户端B)的外部IP和端口号
  327. //
  328. typedef struct _srv_req_tcp_direct_connect
  329. {
  330. _srv_req_tcp_direct_connect ()
  331. : ePacketType ( PACKET_TYPE_TCP_DIRECT_CONNECT )
  332. , dwInvitedID ( 0 )
  333. , nInvitedPort ( 0 )
  334. {
  335. memset ( szInvitedIP, 0, sizeof(szInvitedIP) );
  336. }
  337. PACKET_TYPE ePacketType; // 包类型
  338. DWORD dwInvitedID; // 被邀请方(被动方即客户端B)ID号
  339. char szInvitedIP[32]; // 可以与该IP(被邀请方客户端B的外部IP)地址直接建立TCP连接
  340. UINT nInvitedPort; // 可以与该端口号(被邀请方客户端B的外部IP)地址直接建立TCP连接
  341. } t_SrvReqDirectConnectPkt;
  342. //
  343. // 被动端(客户端B)打洞和侦听均已准备就绪
  344. //
  345. typedef struct _hole_listen_ready
  346. {
  347. _hole_listen_ready ()
  348. : ePacketType ( PACKET_TYPE_HOLE_LISTEN_READY )
  349. , dwInviterID ( 0 )
  350. , dwInviterHoleID ( 0 )
  351. , dwInvitedID ( 0 )
  352. {
  353. }
  354. PACKET_TYPE ePacketType; // 包类型
  355. DWORD dwInviterID; // 发出邀请方(主动方即客户端A)ID号
  356. DWORD dwInviterHoleID; // 发出邀请方(主动方即客户端A)打洞ID号
  357. DWORD dwInvitedID; // 被邀请方(被动方即客户端B)ID号
  358. } t_HoleListenReadyPkt;
  359. CString hwFormatMessage ( DWORD dwErrorCode );
  360. BOOL WaitForThreadEnd ( HANDLE *phThread, DWORD dwWaitTime =5000 );
  361. BOOL WaitForThreadEnd ( HANDLE *pEvtTerminate, HANDLE *phThread, DWORD dwWaitTime =5000 );
  362. #endif