版权声明:本文为博主原创文章,未经博主允许不得转载。

在vs2008中编译通过,vs2010应该也没有问题。

使用静态MFC dll。

其他配置保持默认即可。

可能需要设置/MTD运行时。

可以实现向指定客户端ip发送信息

(该客户端必须首先连接进服务器)

从指定客户端ip中取出数据。

我使用C++类进行了封装,

对各种异常进行了处理。

进行了较详细的注释,

如果有函数不清楚,可以去msdn上查一查。

1,客户端类

[cpp] view plaincopy print?
  1. #pragma once
  2. #define RECEIVE_SIZE 1024
  3. /****************************************************
  4. //Client
  5. function :
  6. save info of client
  7. ***************************************************/
  8. class Client
  9. {
  10. public:
  11. Client();
  12. ~Client();
  13. public:
  14. CCriticalSection    m_cs;
  15. BYTE                m_pRemainBuf[RECEIVE_SIZE];                 //数据缓存区
  16. BYTE                m_nDataLen;                 //数据缓冲区中已有数据的长度
  17. BYTE                m_pReceBuf[RECEIVE_SIZE];                   //接受到的数据
  18. OVERLAPPED          m_OverLapped;
  19. WSABUF              m_DataBuf;
  20. SOCKADDR_IN         m_ClientAddress;
  21. //[!if NET_TYPE_TCP]
  22. SOCKET              m_hClientSock;                            //communication socket;
  23. //[!endif]
  24. public:
  25. //***********将数据存入Client对应的缓冲区中*******************
  26. BOOL    SetData(int len);
  27. //***********从Client对应的缓冲区中取出数据*******************
  28. int     GetData(char * buff, int len);
  29. };

实现:

[cpp] view plaincopy print?
  1. #include "stdafx.h"
  2. #include "Client.h"
  3. /****************************************************************************
  4. *   Name
  5. Client
  6. *   Type
  7. public
  8. *   Function
  9. construction function
  10. *   Return Value
  11. null
  12. *   Parameters
  13. null
  14. *****************************************************************************/
  15. Client::Client()
  16. {
  17. //[!if NET_TYPE_TCP]
  18. m_hClientSock = INVALID_SOCKET;
  19. //[!endif]
  20. m_nDataLen = 0;
  21. memset(m_pRemainBuf, 0, RECEIVE_SIZE);
  22. memset(m_pReceBuf,0,RECEIVE_SIZE);
  23. memset(&m_OverLapped, 0, sizeof(m_OverLapped));
  24. }
  25. /****************************************************************************
  26. *   Name
  27. ~Client
  28. *   Type
  29. public
  30. *   Function
  31. *   Return Value
  32. null
  33. *   Parameters
  34. null
  35. *****************************************************************************/
  36. Client::~Client()
  37. {
  38. int a=0;
  39. a=3;
  40. }
  41. //*********************TCP接受数据************************
  42. //**************缓冲区没有溢出,则将数据追加其后**********
  43. BOOL Client::SetData( int len )
  44. {
  45. if (len<0)
  46. {
  47. return FALSE;
  48. }
  49. if (len==0)
  50. {
  51. return TRUE;
  52. }
  53. m_cs.Lock();
  54. if (m_nDataLen+len>=RECEIVE_SIZE)
  55. {
  56. if (len<RECEIVE_SIZE)
  57. {
  58. memcpy_s(m_pRemainBuf, RECEIVE_SIZE, m_pReceBuf, len);
  59. m_nDataLen = len;
  60. }
  61. else
  62. {
  63. memcpy_s(m_pRemainBuf, RECEIVE_SIZE, m_pReceBuf, RECEIVE_SIZE);
  64. m_nDataLen = (BYTE)RECEIVE_SIZE;
  65. }
  66. }
  67. else
  68. {
  69. memcpy_s(m_pRemainBuf + m_nDataLen, RECEIVE_SIZE-m_nDataLen, m_pReceBuf, len);
  70. m_nDataLen += len;
  71. }
  72. m_cs.Unlock();
  73. return TRUE;
  74. }
  75. int Client::GetData( char * buff, int len )
  76. {
  77. if (!buff)
  78. {
  79. return 0;
  80. }
  81. int result=0;
  82. m_cs.Lock();
  83. if (m_nDataLen <= len)
  84. {
  85. memcpy_s(buff, len, m_pRemainBuf, m_nDataLen);
  86. result = m_nDataLen;
  87. m_nDataLen = 0;
  88. }
  89. else
  90. {
  91. memcpy_s(buff, len, m_pRemainBuf, len);
  92. memmove_s(m_pRemainBuf, RECEIVE_SIZE, m_pRemainBuf + len, m_nDataLen-len);
  93. m_nDataLen -= len;
  94. result = len;
  95. }
  96. m_cs.Unlock();
  97. return result;
  98. }

2,TCP完成端口的封装

头文件:

[cpp] view plaincopy print?
  1. /************************************************************************/
  2. //* 文件名称: IOCP_TCP.h
  3. //* 文件标示:
  4. //* 摘    要:采用完成端口技术处理网络数据
  5. //*
  6. //* 当前版本:1.0
  7. //* 作    者:hxy
  8. //* 完成日期:2013-11-16
  9. //*
  10. /************************************************************************/
  11. #ifndef  _COMPLETIONPORT_H__
  12. #define  _COMPLETIONPORT_H__
  13. #include <winsock2.h>
  14. #include <mswsock.h>
  15. #include "afxmt.h"
  16. #include <vector>
  17. #include "Client.h"
  18. using namespace std;
  19. #pragma once
  20. #define MAXTHREAD_COUNT 8
  21. #define RECEIVE_SIZE  1024
  22. #define PORT 502
  23. class Client;
  24. class CompletionPort
  25. {
  26. public:
  27. CompletionPort();
  28. ~CompletionPort();
  29. //************初始化****************************
  30. //  参数:  需要绑定的ip和port
  31. //  功能: 初始化socket库
  32. //          设置需要绑定的ip和port
  33. //**********************************************
  34. BOOL Init(char * lpszHostAddress, UINT nHostPort);
  35. //************启动******************************
  36. //  功能: 1,启动监听功能; 2,生成完成端口对象
  37. //**********************************************
  38. BOOL Active(void);
  39. //************停止******************************
  40. //  功能: 停止监听功能,
  41. //          释放Active中的申请的所有资源
  42. //**********************************************
  43. BOOL Close(void);
  44. //************接受数据**************************
  45. //  功能: 接受指定客户端ip的数据
  46. //  参数:  buff:指向接受数据的缓冲区
  47. //          len:  缓冲区的大小
  48. //          ip:   客户端ip,如192.168.31.27
  49. //  说明:  buff的内存由调用者提供
  50. //**********************************************
  51. int ReceiveData(char * buff, int len, char * ip);
  52. //************发送数据***************************
  53. //  功能: 向指定的客户端ip的数据
  54. //  参数:  buff:指向发送数据的缓冲区
  55. //          len:  缓冲区的大小
  56. //          ip:   客户端ip,如192.168.31.27
  57. //**********************************************
  58. int SendData(const char * buff, int len, char * ip);
  59. //-------------------------内部使用--------------------------------
  60. //************监听*******************************
  61. //  功能: 监听客户端连接线程
  62. //***********************************************
  63. void MonitorServerSocket();
  64. //************监听客户端发送的数据***************
  65. //  功能: 监听客户端连接线程函数
  66. //***********************************************
  67. void MonitorIoCompletionPort();
  68. //************处理客户端连接*********************
  69. //  功能: 客户端连接处理函数
  70. //***********************************************
  71. void OnClientAccept();
  72. //************处理客户端关闭*********************
  73. //  功能: 客户端关闭处理函数
  74. //***********************************************
  75. BOOL OnClientClose(DWORD dwSockId);
  76. private:
  77. //************初始化Socket库*********************
  78. //  功能: 初始化Socket库
  79. //***********************************************
  80. BOOL InitWinsock();
  81. void ProcessData(Client* pClient);
  82. Client* GetClient(DWORD dwSockId, int& index);
  83. //----------------------------Client 管理-------------------------
  84. //************增加客户端*********************
  85. BOOL AddClient( Client * const pClient);
  86. //************删除客户端*********************
  87. BOOL DeleteClient( int index);
  88. //************查询客户端*********************
  89. Client * GetClient( const char * ip);
  90. private:
  91. SOCKADDR_IN m_HostAddress;                          //服务器端地址(ip,port,协议)等
  92. vector<Client*> m_ClientVector;                       //客户端表
  93. rec_lock m_cs;                              //客户端表同步
  94. BOOL            m_bIsQuit;                          //退出标识
  95. HANDLE          m_hQuitEvent;                       //退出事件句柄
  96. HANDLE          m_hCOP;                             //完成端口句柄
  97. HANDLE          m_hThreadArray[MAXTHREAD_COUNT];    //接收数据线程句柄
  98. int             m_nThreadArray;                     //接收数据线程数量
  99. HANDLE          m_hListen;                          //监听连接线程句柄
  100. SOCKET          m_ListenSocket;                     //监听socket
  101. BOOL            m_bQuitThread;                      //监听线程退出标识
  102. WSAEVENT        m_wsaEvent;                         //网络事件
  103. };
  104. #endif

实现文件:

[cpp] view plaincopy print?
  1. #include "StdAfx.h"
  2. #include "IOCP_TCP.h"
  3. #ifdef _DEBUG
  4. #define new DEBUG_NEW
  5. #undef THIS_FILE
  6. static char THIS_FILE[] = __FILE__;
  7. #endif
  8. /****************************************************************************
  9. *   Name
  10. ThreadTcpServer
  11. *   Type
  12. public
  13. *   Function
  14. thread to monitor a socket and accept a link
  15. *   Return Value
  16. DWORD WINAPI
  17. *   Parameters
  18. void * lpParameter
  19. *****************************************************************************/
  20. DWORD WINAPI ThreadTcpServer(void * lpParameter)
  21. {
  22. CompletionPort* pCpPort = (CompletionPort*)lpParameter;
  23. pCpPort->MonitorServerSocket();
  24. return 0;
  25. }
  26. /****************************************************************************
  27. *   Name
  28. CompletionRoutine
  29. *   Type
  30. public
  31. *   Function
  32. work thread of completionport
  33. *   Return Value
  34. DWORD WINAPI
  35. *   Parameters
  36. void * lpParameter translate a pointer of this
  37. *****************************************************************************/
  38. DWORD WINAPI  CompletionRoutine(void * lpParameter)
  39. {
  40. CompletionPort* pCpPort = (CompletionPort*)lpParameter;
  41. pCpPort->MonitorIoCompletionPort();
  42. return 0;
  43. }
  44. /****************************************************************************
  45. *   Name
  46. CompletionPort
  47. *   Type
  48. public
  49. *   Function
  50. constructor
  51. *   Return Value
  52. null
  53. *   Parameters
  54. null
  55. *****************************************************************************/
  56. CompletionPort::CompletionPort()
  57. {
  58. //_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF| _CRTDBG_LEAK_CHECK_DF);
  59. m_hCOP = INVALID_HANDLE_VALUE;
  60. m_hListen = INVALID_HANDLE_VALUE;
  61. for (int i=0; i< MAXTHREAD_COUNT; i++)
  62. {
  63. m_hThreadArray[i] = INVALID_HANDLE_VALUE;
  64. }
  65. m_bQuitThread = FALSE;
  66. m_wsaEvent = NULL;
  67. m_ListenSocket = INVALID_SOCKET;
  68. m_ClientVector.clear();
  69. m_bIsQuit = FALSE;
  70. m_hQuitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  71. m_nThreadArray = 0;
  72. }
  73. /****************************************************************************
  74. *   Name
  75. ~CompletionPort
  76. *   Type
  77. public
  78. *   Function
  79. do sth to release memory
  80. *   Return Value
  81. null
  82. *   Parameters
  83. null
  84. *****************************************************************************/
  85. CompletionPort::~CompletionPort()
  86. {
  87. int i = 0;
  88. m_bIsQuit = TRUE;
  89. Sleep(10);
  90. if (INVALID_HANDLE_VALUE != m_hCOP)
  91. {
  92. m_bIsQuit = TRUE;
  93. //等待所有接受数据的线程结束
  94. WaitForMultipleObjects(m_nThreadArray, m_hThreadArray, TRUE, INFINITE);
  95. while (INVALID_HANDLE_VALUE != m_hThreadArray[i])
  96. {
  97. CloseHandle(m_hThreadArray[i]);
  98. m_hThreadArray[i-1] = INVALID_HANDLE_VALUE;
  99. i++;
  100. }
  101. //关闭完成端口
  102. CloseHandle(m_hCOP);
  103. m_hCOP=NULL;
  104. }
  105. // 关闭监听socket
  106. if (INVALID_SOCKET != m_ListenSocket)
  107. {
  108. closesocket(m_ListenSocket);
  109. m_ListenSocket = NULL;
  110. }
  111. // 关闭监听线程
  112. m_bQuitThread = TRUE;
  113. WaitForSingleObject(m_hListen, INFINITE);
  114. if (INVALID_HANDLE_VALUE != m_hListen)
  115. {
  116. CloseHandle(m_hListen);
  117. m_hListen = NULL;
  118. }
  119. WSACloseEvent(m_wsaEvent);
  120. m_wsaEvent = NULL;
  121. // 关闭客户端连接socket
  122. for( size_t i=0; i<m_ClientVector.size(); i++)
  123. {
  124. Client* pClient = m_ClientVector[i];
  125. if( pClient != NULL)
  126. {
  127. if (pClient->m_hClientSock != INVALID_SOCKET)
  128. {
  129. shutdown(pClient->m_hClientSock, 2);
  130. closesocket(pClient->m_hClientSock);
  131. pClient->m_hClientSock = INVALID_SOCKET;
  132. }
  133. delete pClient;
  134. pClient = NULL;
  135. }
  136. }
  137. CloseHandle(m_hQuitEvent);
  138. m_ClientVector.clear();
  139. }
  140. BOOL CompletionPort::Init(char * lpszHostAddress, UINT nHostPort)
  141. {
  142. if (!InitWinsock())
  143. {
  144. return FALSE;
  145. }
  146. m_HostAddress.sin_family = AF_INET;
  147. m_HostAddress.sin_addr.s_addr = inet_addr((char *)lpszHostAddress);
  148. if (m_HostAddress.sin_addr.s_addr == INADDR_NONE)
  149. {
  150. LPHOSTENT lphost;
  151. lphost = gethostbyname((char *)lpszHostAddress);
  152. if (lphost != NULL)
  153. m_HostAddress.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
  154. else
  155. {
  156. WSASetLastError(WSAEINVAL);
  157. return FALSE;
  158. }
  159. }
  160. m_HostAddress.sin_port = htons((u_short)nHostPort);
  161. return true;
  162. }
  163. //************启动******************************
  164. //  功能: 启动监听功能
  165. //**********************************************
  166. BOOL CompletionPort::Active()
  167. {
  168. //-------------------------------监听连接---------------------------------------
  169. //创建监听Socket
  170. m_ListenSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
  171. if (INVALID_SOCKET == m_ListenSocket)
  172. {
  173. return FALSE;
  174. }
  175. int nResult = bind(m_ListenSocket, (PSOCKADDR)&m_HostAddress, sizeof(m_HostAddress));
  176. if (SOCKET_ERROR == nResult)
  177. {
  178. closesocket(m_ListenSocket);
  179. return FALSE;
  180. }
  181. nResult = listen(m_ListenSocket, 20);
  182. if (SOCKET_ERROR == nResult)
  183. {
  184. closesocket(m_ListenSocket);
  185. return FALSE;
  186. }
  187. m_wsaEvent = WSACreateEvent();
  188. if (NULL == m_wsaEvent)
  189. {
  190. return FALSE;
  191. }
  192. WSAEventSelect(m_ListenSocket, m_wsaEvent, FD_ACCEPT);
  193. //创建监听连接的线程
  194. m_hListen = CreateThread(NULL, 0, ThreadTcpServer, (LPVOID)this, 0, NULL);
  195. if (NULL == m_hListen)
  196. {
  197. return FALSE;
  198. }
  199. //-------------------------------完成端口---------------------------------------
  200. //创建完成端口句柄
  201. m_hCOP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);
  202. if (NULL == m_hCOP)
  203. {
  204. return FALSE;
  205. }
  206. //创建处理数据的线程
  207. SYSTEM_INFO SysInfo;
  208. GetSystemInfo(&SysInfo);
  209. for (int i=0; i<(int)SysInfo.dwNumberOfProcessors && (i<MAXTHREAD_COUNT); i++)
  210. {
  211. m_hThreadArray[i] = CreateThread(NULL, 0, CompletionRoutine, (LPVOID)this, 0, NULL);
  212. if (NULL == m_hThreadArray[i])
  213. {
  214. while (i>0)
  215. {
  216. CloseHandle(m_hThreadArray[i-1]);
  217. m_hThreadArray[i-1] = INVALID_HANDLE_VALUE;
  218. i--;
  219. }
  220. return FALSE;
  221. }
  222. m_nThreadArray ++;
  223. }
  224. return TRUE;
  225. }
  226. //************从完成端口取数据******************
  227. //  功能: 从完成端口取数据
  228. //  返回: 字节数,如果ip未连接则返回0
  229. //**********************************************
  230. int CompletionPort::ReceiveData(char * buff, int len, char * ip)
  231. {
  232. if (!buff || !ip)
  233. {
  234. return 0;
  235. }
  236. Client * pClient = GetClient(ip);
  237. if (!pClient)
  238. {
  239. return 0;
  240. }
  241. return pClient->GetData(buff, len);
  242. }
  243. //************发送数据***************************
  244. //  功能: 向指定的客户端ip的数据
  245. //  参数:  buff:指向发送数据的缓冲区
  246. //          len:  要发送的数据的字节数
  247. //          ip:   客户端ip,如192.168.31.27
  248. //  返回: 发送的字节数,错误则返回0
  249. //**********************************************
  250. int CompletionPort::SendData(const char * buff, int len, char * ip)
  251. {
  252. if (!buff || !ip)
  253. {
  254. return 0;
  255. }
  256. int ret =0;
  257. //在取得客户端指针之后,完成端口线程会删除该客户端,
  258. //可能造成最null指针的解引用,所有这里使用结构化异常进行处理
  259. __try
  260. {
  261. Client * pClient = GetClient(ip);
  262. if (!pClient)
  263. {
  264. return 0;
  265. }
  266. DWORD result = 0;
  267. ret =send(pClient->m_hClientSock, buff, len, 0);
  268. //int ret = WriteFile((HANDLE)pClient->m_hClientSock, buff, len, &result, NULL);
  269. }
  270. __except (EXCEPTION_EXECUTE_HANDLER)
  271. {
  272. printf("客户端已被删除,发送失败");
  273. }
  274. return ret;
  275. }
  276. /****************************************************************************
  277. *   Name
  278. InitWinsock
  279. *   Type
  280. public
  281. *   Function
  282. initialize socket
  283. *   Return Value
  284. BOOL
  285. *   Parameters
  286. null
  287. *****************************************************************************/
  288. BOOL CompletionPort::InitWinsock()
  289. {
  290. WSADATA wsd;
  291. int nResult = WSAStartup(MAKEWORD(2,2), &wsd);
  292. if (0 != nResult)
  293. {
  294. return FALSE;
  295. }
  296. return TRUE;
  297. }
  298. /****************************************************************************
  299. *   Name
  300. MonitorServerSocket
  301. *   Type
  302. public
  303. *   Function
  304. function to monitor a socket and accept a link
  305. *   Return Value
  306. null
  307. *   Parameters
  308. null
  309. *****************************************************************************/
  310. void CompletionPort::MonitorServerSocket()
  311. {
  312. DWORD   dwWaitCode;
  313. WSANETWORKEVENTS wsaNetWorkEvents;
  314. while( true )
  315. {
  316. if( m_bQuitThread )                 //判断监听线程退出条件是否满足
  317. {
  318. SetEvent(m_hQuitEvent);
  319. TRACE("Monitor Server Quit\n");
  320. return ;
  321. }
  322. dwWaitCode = WSAWaitForMultipleEvents(1, &m_wsaEvent, FALSE, 2000, FALSE);//等待网络事件
  323. if(dwWaitCode != WAIT_OBJECT_0)
  324. continue;
  325. if( SOCKET_ERROR == WSAEnumNetworkEvents(m_ListenSocket, m_wsaEvent,&wsaNetWorkEvents ))//枚举网络事件
  326. {
  327. int nErrorCode = WSAGetLastError();
  328. TRACE("WSAEnumNetworkEvents Error");
  329. }
  330. else
  331. {
  332. if( wsaNetWorkEvents.lNetworkEvents & FD_ACCEPT)
  333. {
  334. OnClientAccept();
  335. }
  336. }
  337. }
  338. }
  339. /****************************************************************************
  340. *   Name
  341. OnClientAccept
  342. *   Type
  343. public
  344. *   Function
  345. function to monitor a socket and accept a link
  346. *   Return Value
  347. null
  348. *   Parameters
  349. null
  350. *****************************************************************************/
  351. void CompletionPort::OnClientAccept()
  352. {
  353. int nSockAddrLength = sizeof(SOCKADDR_IN);
  354. Client* pClntData = new Client();
  355. pClntData->m_hClientSock = accept(m_ListenSocket,
  356. (struct sockaddr*)&(pClntData->m_ClientAddress),
  357. &nSockAddrLength);
  358. if (INVALID_SOCKET == pClntData->m_hClientSock)
  359. {
  360. delete pClntData;
  361. }
  362. AddClient(pClntData);
  363. HANDLE hCompletePort = CreateIoCompletionPort((HANDLE)pClntData->m_hClientSock, m_hCOP,
  364. (DWORD)pClntData->m_hClientSock,0);
  365. if( hCompletePort != m_hCOP)
  366. {
  367. TRACE("Create Communication CompletionPort failure!\n");
  368. }
  369. ReadFile((HANDLE)pClntData->m_hClientSock, pClntData->m_pReceBuf, RECEIVE_SIZE, NULL,
  370. &pClntData->m_OverLapped);
  371. }
  372. /****************************************************************************
  373. *   Name
  374. MonitorIoCompletionPort
  375. *   Type
  376. public
  377. *   Function
  378. function to monitor completionport
  379. *   Return Value
  380. void
  381. *   Parameters
  382. null
  383. *****************************************************************************/
  384. void CompletionPort::MonitorIoCompletionPort()
  385. {
  386. TRACE("Begin Monitor IoPort \n");
  387. BOOL  bSuc       = FALSE;
  388. DWORD dwNumBytes = 0;
  389. DWORD dwKey      = -1;
  390. DWORD dwSockId = 0;
  391. LPOVERLAPPED completedOverlapped;
  392. int nLen =0;
  393. while( true )
  394. {
  395. //判断监听线程退出条件是否满足
  396. if( m_bIsQuit)
  397. {
  398. TRACE("Monitor IoCompletionPort Quit\n");
  399. SetEvent(m_hQuitEvent);
  400. return;
  401. }
  402. //查询完全端口状态
  403. dwKey = -1;
  404. bSuc  = GetQueuedCompletionStatus( m_hCOP, &dwNumBytes, &dwKey, &completedOverlapped, 2000);
  405. if (bSuc==FALSE)
  406. {
  407. int nError = WSAGetLastError();
  408. if (nError == WSA_WAIT_TIMEOUT)
  409. {
  410. continue;
  411. }
  412. if (nError == ERROR_NETNAME_DELETED)
  413. {
  414. OnClientClose(dwKey);
  415. continue;
  416. }
  417. TRACE("GetQueuedCompletionStatus Error: %d\n", nError);
  418. continue;
  419. }
  420. if (dwKey>0)
  421. {
  422. dwSockId  = dwKey;
  423. nLen = dwNumBytes;
  424. if( nLen > 0)
  425. {
  426. int index = -1;
  427. Client* pClient = GetClient(dwSockId, index);
  428. if( pClient == NULL)
  429. continue;
  430. try
  431. {
  432. //Sleep(50);
  433. if (nLen >1024)
  434. {
  435. nLen = 1024;
  436. //CDebug::ShowErroMessage("接收到数据长度过长!");
  437. }
  438. pClient->SetData(nLen);
  439. //ProcessData(pClient);
  440. //向完全端口发送读指令,等待下一次数据
  441. ZeroMemory(pClient->m_pReceBuf,RECEIVE_SIZE);
  442. ReadFile((HANDLE)pClient->m_hClientSock,pClient->m_pReceBuf,RECEIVE_SIZE,NULL,&pClient->m_OverLapped);
  443. }
  444. catch(...)
  445. {
  446. TRACE("catch an error");
  447. }
  448. }
  449. else
  450. {
  451. OnClientClose(dwSockId);
  452. }
  453. }
  454. }
  455. }
  456. /****************************************************************************
  457. *   Name
  458. GetClient
  459. *   Type
  460. public
  461. *   Function
  462. get a pointer to point class of  Client
  463. *   Return Value
  464. Client*
  465. *   Parameters
  466. DWORD dwSockId : socket ID
  467. int& index: the position in the vector
  468. *****************************************************************************/
  469. Client* CompletionPort::GetClient(DWORD dwSockId, int& index)
  470. {
  471. Client* pNewData = NULL;
  472. m_cs.lock();
  473. for (size_t i = 0; i < m_ClientVector.size(); i++)
  474. {
  475. if (m_ClientVector[i]->m_hClientSock == dwSockId)
  476. {
  477. index = i;
  478. pNewData = m_ClientVector[i];
  479. break;
  480. }
  481. }
  482. m_cs.unlock();
  483. return pNewData;
  484. }
  485. /****************************************************************************
  486. *   Name
  487. OnClientClose
  488. *   Type
  489. public
  490. *   Function
  491. close the socket that dont translate data
  492. *   Return Value
  493. BOOL
  494. *   Parameters
  495. DWORD dwSockId: socket ID
  496. *****************************************************************************/
  497. BOOL CompletionPort::OnClientClose(DWORD dwSockId)
  498. {
  499. int index = -1;
  500. Client* pClient = GetClient(dwSockId, index);
  501. if ((NULL != pClient) && (-1 != index))
  502. {
  503. closesocket(pClient->m_hClientSock);
  504. DeleteClient(index);
  505. pClient = NULL;
  506. }
  507. return TRUE;
  508. }
  509. //----------------------------Client 管理-------------------------
  510. //************增加客户端*********************
  511. BOOL CompletionPort::AddClient(Client * const pClient)
  512. {
  513. if (!pClient)
  514. {
  515. return FALSE;
  516. }
  517. m_cs.lock();
  518. m_ClientVector.push_back(pClient);
  519. m_cs.unlock();
  520. return TRUE;
  521. }
  522. //************删除客户端*********************
  523. BOOL CompletionPort::DeleteClient(int index)
  524. {
  525. m_cs.lock();
  526. delete m_ClientVector[index];
  527. m_ClientVector.erase(m_ClientVector.begin() + index);
  528. m_cs.unlock();
  529. return TRUE;
  530. }
  531. //************查询客户端*********************
  532. Client * CompletionPort::GetClient(const char * ip)
  533. {
  534. Client* pNewClient = NULL;
  535. ULONG nAddr = inet_addr(ip);
  536. m_cs.lock();
  537. for (size_t i = 0; i < m_ClientVector.size(); i++)
  538. {
  539. if (m_ClientVector[i]->m_ClientAddress.sin_addr.s_addr == nAddr)
  540. {
  541. pNewClient = m_ClientVector[i];
  542. break;
  543. }
  544. }
  545. m_cs.unlock();
  546. return pNewClient;
  547. }

3,测试文件:

[cpp] view plaincopy print?
  1. // IOCPTest.cpp : 定义控制台应用程序的入口点。
  2. //
  3. #include "stdafx.h"
  4. #include "IOCP_TCP.h"
  5. #include <iostream>
  6. int _tmain(int argc, _TCHAR* argv[])
  7. {
  8. CCriticalSection *p = new CCriticalSection;
  9. delete p;
  10. CompletionPort * cp = new CompletionPort();
  11. cp->Init("192.168.31.27", 4567);           //需要修改为自己的ip
  12. cp->Active();
  13. char buff[1024]={0};
  14. char recBuff[1024]={0};
  15. int len;
  16. while (true)
  17. {
  18. scanf_s("%s", buff, 1023);
  19. len = strlen(buff);
  20. cp->SendData(buff, len, "192.168.31.27");<span style="white-space:pre">  </span>//客户端的ip
  21. ZeroMemory(recBuff,1024);
  22. cp->ReceiveData(recBuff, 1024, "192.168.31.27");     //客户端的ip
  23. printf("\n%s\n", recBuff);
  24. }
  25. delete cp;
  26. return 0;
  27. }

5,预编译头文件

[cpp] view plaincopy print?
  1. // stdafx.h : include file for standard system include files,
  2. //  or project specific include files that are used frequently, but
  3. //      are changed infrequently
  4. //
  5. #if _MSC_VER > 1000
  6. #pragma once
  7. #endif // _MSC_VER > 1000
  8. #define _WIN32_WINNT    0x0501
  9. #define VC_EXTRALEAN        // Exclude rarely-used stuff from Windows headers
  10. #include <afxwin.h>         // MFC core and standard components
  11. #include <afxext.h>         // MFC extensions
  12. #ifndef _AFX_NO_OLE_SUPPORT
  13. #include <afxole.h>         // MFC OLE classes
  14. #include <afxodlgs.h>       // MFC OLE dialog classes
  15. #include <afxdisp.h>        // MFC Automation classes
  16. #endif // _AFX_NO_OLE_SUPPORT
  17. #ifndef _AFX_NO_DB_SUPPORT
  18. #include <afxdb.h>            // MFC ODBC database classes
  19. #endif // _AFX_NO_DB_SUPPORT
  20. #ifndef _AFX_NO_DAO_SUPPORT
  21. #include <afxdao.h>           // MFC DAO database classes
  22. #endif // _AFX_NO_DAO_SUPPORT
  23. #include <afxdtctl.h>     // MFC support for Internet Explorer 4 Common Controls
  24. #ifndef _AFX_NO_AFXCMN_SUPPORT
  25. #include <afxcmn.h>           // MFC support for Windows Common Controls
  26. #endif // _AFX_NO_AFXCMN_SUPPORT
  27. //外部库文件引用
  28. #include <afxmt.h>
  29. #include <afx.h>
  30. #include <afxtempl.h>
  31. #include <winsock2.h>
  32. #include <memory>
  33. //外部自定义头文件引用
  34. //#include "Resource.h"
  35. //#include "ICOMPro.h"
  36. //#include "datatype.h"
  37. //#include "Reg.h"
  38. //#include "Debug.h"
  39. //#include "Helper.h"
  40. #if defined(_WIN32_WCE_CEPC) || defined(_ARM_)
  41. #include "AtomCE.h"
  42. #endif
  43. //编译选项
  44. //[!if TRYCONNECT_TRUE]
  45. //#define _TRYCONNECT_TRUE
  46. //[!endif]
  47. //
  48. //[!if TRYCONNECT_USERDEFINE]
  49. //#define _TRYCONNECT_USEDEFINE
  50. //[!endif]
  51. //
  52. //[!if TRYCONNECT_USEPACKET]
  53. //#define _TRYCONNECT_USEPACKET
  54. //[!endif]
  55. //
  56. //[!if REOPENCOM]
  57. //#define _REOPENCOM
  58. //[!endif]
  59. //{{AFX_INSERT_LOCATION}}
  60. // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
  61. #include "lock.h"

此文章来自于【http://blog.csdn.net/huangxy10/article/details/16899481】

TCP完成端口服务器构建相关推荐

  1. Linux服务器上测试TCP/UDP端口的连通性

    目录 说明 测试tcp端口的连通性: 使用nc命令来测试udp端口的连通性: 使用nc命令来测试tcp端口的连通性: 使用案例如下: 说明 翻译自: How to Test Port[TCP/UDP] ...

  2. 阿里云建站,重启阿里云服务器后网站打不开,该怎么办???如何检查TCP 80端口是否正常工作???

    阿里云建站,重启阿里云服务器后网站打不开,该怎么办???如何检查TCP 80端口是否正常工作??? 本篇适用于阿里云云服务器ECS. 一.云服务器ECS为Ubuntu服务器 以下是在Ubuntu 16 ...

  3. 阿里云-默认封禁TCP 25端口出方向的访问流量,即您无法在阿里云上的云服务器通过TCP 25端口连接外部地址。

    TCP 25端口解封申请 本页目录 背景信息 操作步骤 出于安全考虑,阿里云默认封禁TCP 25端口出方向的访问流量,即您无法在阿里云上的云服务器通过TCP 25端口连接外部地址. 背景信息 TCP ...

  4. linux系统怎么测试udp端口通不通,怎么在Linux服务器上测试TCP/UDP端口的连通性?...

    翻译自: How to Test Port[TCP/UDP] Connectivity from a Linux Server (文档 ID 2212626.1) 适用于: Linux OS - Ve ...

  5. 优化Linux内核参数/etc/sysctl.conf sysctl 《高性能Linux服务器构建实战:运维监控、性能调优与集群应用》...

    优化Linux内核参数/etc/sysctl.conf  sysctl  <高性能Linux服务器构建实战:运维监控.性能调优与集群应用> http://book.51cto.com/ar ...

  6. arm学习笔记005之Linux平台下TFTP服务器构建

    TFTP(Trivial File Transfer Protocol,简单的文件传输协议)是 TCP/IP 协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供不复杂.开销不大的文件传 ...

  7. DNS服务器(DNS服务器构建,特殊的解析记录,多域名DNS服务器架构,DNF主从架构,DNS主从数据同步)

    学前提示: 需要两台虚拟机 虚拟机A:主机名位svr7 IP:192.168.4.7 虚拟机B:主机名pc207 IP:192.168.207 一.进行环境的设置 1.修改两台虚拟机的SELinux ...

  8. 计算机网络套接字编程实验-TCP单进程循环服务器程序与单进程客户端程序(简单回声)

    1.实验系列 ·Linux NAP-Linux网络应用编程系列 2.实验目的 ·理解并掌握在程序运行时从命令行读取数据的C语言编程方法: ·理解并掌握基于命令参数设置并获取IP与Port的C语言编程方 ...

  9. 计算机网络套接字编程实验-TCP多进程并发服务器程序与单进程客户端程序(简单回声)

    1.实验系列 ·Linux NAP-Linux网络应用编程系列 2.实验目的 ·理解多进程(Multiprocess)相关基本概念,理解父子进程之间的关系与差异,熟练掌握基于fork()的多进程编程模 ...

  10. 高性能Linux服务器构建实战 服务器安全运维

    文章目录 1. 安全运维 1.1 账户和登录安全 1.1.1 用户和用户组管理 1.1.2 系统服务管理 1.1.3 登录密码安全管理 1.1.4 用户root权限管理 1.1.5 系统欢迎页面管理 ...

最新文章

  1. DTrace memory leak 内存泄露
  2. CentOS6.5-源码编译安装最新MySQL5.7.10
  3. vuex实践之路——笔记本应用(三)
  4. 虚幻gameframe_【虚幻4】从0开始的Galgame开发框架(2)--MainManager
  5. 文本处理三剑客之sed
  6. SpringBoot异常处理-自定义HandlerExceptionResolver
  7. 走访近20家代工厂后:近千块的大牌T恤,成本只要几十块
  8. agaular 离线文档_Zeal 国外一款面向开发者的离线文档查看工具
  9. DIV的摇晃效果---jquery实现
  10. 2.《Spring学习笔记-MVC》系列文章,讲解返回json数据的文章共有3篇,分别为:...
  11. jq方法中 $(window).load() 与 $(document).ready() 的区别
  12. Java调用so文件
  13. cat6 万兆_专业扫盲Cat5e/Cat6/Cat6a/Cat7网线系列
  14. Flink1.12 文档
  15. 获取视频旋转角度,并对视频进行旋转
  16. 2022年2月语音合成(TTS)和语音识别(ASR)论文月报
  17. 【杂七杂八】Dreamweaver在Surface高分辨率下工具栏字体和按钮太小的解决办法
  18. Python解炸金花问题
  19. 利用SUS实现自动补丁管理
  20. vue-chartjs画渐变色

热门文章

  1. 中兴WCDMA模块 Linux拨号流程
  2. Framework类库
  3. PICKIT3与ICD2比较。正在等待PICKIT3到货。
  4. 信息系统监理工程师模拟题
  5. mac/windows用Chrome浏览器截取长图
  6. 未来教育python有错吗_未来教育题库错误大列举,建议不要用它的题库复习了
  7. 文本溢出处理,出现省略号,单行文本溢出处理,多行文本溢出处理
  8. Percona数据库备份
  9. 多序列比对---ClustalX比对GeneDoc美化
  10. 7月1号连连支付不能提现PayPal了,以后PayPal怎样提现?