=================================版权声明=================================

版权声明:原创文章 禁止转载 

请通过右侧公告中的“联系邮箱(wlsandwho@foxmail.com)”联系我

勿用于学术性引用。

勿用于商业出版、商业印刷、商业引用以及其他商业用途。                   

 

本文不定期修正完善。

本文链接:http://www.cnblogs.com/wlsandwho/p/5427091.html

耻辱墙:http://www.cnblogs.com/wlsandwho/p/4206472.html

=======================================================================

先放个草稿。有空写写,没空就算了。

=======================================================================

简单的做了几个类。

把Socket部分、IOCP部分、线程部分分割开。便于实现自己想要的样子。实现了ACCEPT、RECV的自定义处理。

 

没有写SEND部分。

=======================================================================

头文件

  1 #pragma once
  2 
  3 //SIT--Socket,IOCP,Thread Pool
  4 //by wls
  5 //20160419
  6 #include <list>
  7 
  8 #include <atlstr.h>
  9 
 10 #include <winsock2.h>
 11 #include <MSWSock.h>
 12 #include <Ws2tcpip.h>
 13 #pragma comment(lib,"ws2_32.lib")
 14 
 15 #include <functional>
 16 #include <memory>
 17 //缓冲区最大大小
 18 static const int BUFFER_SIZE_MAX = 3096;
 19 
 20 class CPerIOContextBase;
 21 class CPerSocketContextBase;
 22 class CSITContextBase;
 23 class CSocketNetBase;
 24 class CIOCPBase;
 25 class CThreadpoolBase;
 26 class CSITBase;
 27 
 28 //操作类型
 29 typedef enum _OPERATION_TYPE
 30 {
 31     NULL_POSTED=0,        // 用于初始化,无意义
 32     ACCEPT_POSTED,        // 标志投递的Accept操作
 33     SEND_POSTED,        // 标志投递的是发送操作
 34     RECV_POSTED            // 标志投递的是接收操作
 35 }OPERATION_TYPE;
 36 
 37 //工作线程单元
 38 typedef struct _WorkerThreadUnit
 39 {
 40     CSITBase* pSIT;        //SIT指针
 41     DWORD dwThreadID;    //线程ID
 42 }WorkerThreadUnit, *PWorkerThreadUnit;
 43 
 44 //SIT
 45 class CSITBase
 46 {
 47 public:
 48     virtual bool Init(CIOCPBase* pIOCP, CThreadpoolBase* pThreadpool, CSocketNetBase* pSocketSocket,CSITContextBase* pSITContext);
 49 public:
 50     virtual bool AssociateSocketNetWithIOCP(CPerSocketContextBase* pSocketContext);
 51     virtual bool HandleError(CPerSocketContextBase* pSocketContext, DWORD dwError, DWORD dwThreadID);
 52     virtual bool PostAccept(CPerIOContextBase* pAcceptContext);
 53     virtual bool DoAccept(CPerSocketContextBase* pSocketContext, CPerIOContextBase* pIOContext);
 54     virtual bool DoRecv(CPerSocketContextBase* pSocketContext, CPerIOContextBase* pIOContext);
 55     virtual void AddSocketContext(CPerSocketContextBase* pSocketContext);
 56     virtual void RemoveSocketContext(CPerSocketContextBase* pSocketContext);
 57 public:
 58     CIOCPBase* GetIOCP();
 59     CSITContextBase* GetSITContext();
 60     CThreadpoolBase* GetThreadpool();
 61     CSocketNetBase* GetSocketNet();
 62     HANDLE GetIOCPObj();
 63 protected:
 64     CIOCPBase* m_pIOCP;
 65     CThreadpoolBase* m_pThreadpool;
 66     CSocketNetBase* m_pSocketNet;
 67     CSITContextBase* m_pSITContext;
 68 };
 69 
 70 //每次IO要用到的结构
 71 class CPerIOContextBase
 72 {
 73 public:
 74     CPerIOContextBase();
 75     ~CPerIOContextBase();
 76 
 77 public:
 78     //重置缓冲区
 79     void ResetBuffer();
 80 
 81 public:
 82     //位于首部
 83     OVERLAPPED overlapped;
 84     //套接字
 85     SOCKET socket;
 86     //WSABUF结构,其buf字段指向szBuffer
 87     WSABUF wsaBuf;
 88     //实际缓冲区
 89     char szBuffer[BUFFER_SIZE_MAX];
 90     //本次IO操作的类型
 91     OPERATION_TYPE operationtype;
 92 };
 93 //每个Socket要用到的结构
 94 class CPerSocketContextBase
 95 {
 96 public:
 97     CPerSocketContextBase();
 98     ~CPerSocketContextBase();
 99 public:
100     //获得一个新的单次IO上下文
101     virtual CPerIOContextBase* GetNewPerIOContext();
102     //删除指定的单次IO上下文
103     virtual void RemovePerIOContext(CPerIOContextBase* pPerIOContext);
104 public:
105     SOCKET socket;
106     SOCKADDR_IN socketaddr;
107     std::list<CPerIOContextBase*> listPerIOContext;//该套接字中用到的所有的单次IO上下文都放在这里
108 };
109 
110 //容纳所有的CPerSocketContextBase
111 //其中每一个CPerSocketContextBase中又容纳了它所对应的所有的CPerIOContextBase
112 class CSITContextBase
113 {
114 public:
115     virtual bool Init();
116 public:
117     virtual void AddSocketContext(CPerSocketContextBase* pSocketContext);
118     virtual void RemoveSocketContext(CPerSocketContextBase* pSocketContext);
119 protected:
120     CRITICAL_SECTION m_cs;
121     std::list<CPerSocketContextBase*> m_listPerSocketContext;
122 };
123 
124 //IOCP
125 class CIOCPBase
126 {
127 public:
128     virtual bool Init(CSITBase* pSIT);
129     HANDLE Associate(HANDLE hFileHandle, HANDLE ExistingCompletionPort, ULONG_PTR CompletionKey);
130     virtual bool HandleError(CPerSocketContextBase* pSocketContext,DWORD dwError,DWORD dwThreadID);
131 
132 protected:
133     HANDLE Create(int nConcurrentThread = 0);
134     
135 public:
136     HANDLE GetIOCPObj();
137     CSITBase* GetSIT();
138 
139 protected:
140     HANDLE m_hIOCompletionPort;
141     CSITBase* m_pSIT;
142 };
143 
144 //用户操作
145 class CUserOperationBase
146 {
147 public:
148     virtual bool DoAccept(LPVOID pVoid);
149     virtual bool DoRecv(LPVOID pVoid);
150     virtual bool DoPost(LPVOID pVoid);
151 };
152 
153 
154 //线程池
155 class CThreadpoolBase
156 {
157 public:
158     CThreadpoolBase();
159     ~CThreadpoolBase();
160 public:
161     virtual bool Init(CSITBase* pSIT);
162 
163 protected:
164     //获得合理线程总数
165     virtual int GetNumOfThreads(int nAdjustment = 2);
166 
167 protected:
168     //线程工作函数
169     static DWORD WINAPI WorkerThread(LPVOID lpParam);
170 
171 protected:
172     HANDLE* m_phWorkerThreads;
173     int m_NumOfThreads;
174 
175 protected:
176 
177     CSITBase* m_pSIT;
178 };
179 
180 //网络套接字
181 class CSocketNetBase
182 {
183 public:
184     //用户操作函数
185     typedef std::function<bool(LPVOID)> FuncUserOperation;
186 
187     //设置用户操作
188     virtual bool SetUserOperation(OPERATION_TYPE eOperationType,FuncUserOperation pFunc);
189 public:
190     CSocketNetBase();
191 
192 public:
193     static    bool IsAlive(SOCKET& s);
194 
195 public:
196     virtual bool Init(CSITBase* pSIT);
197 public:
198     virtual bool PostAccept(CPerIOContextBase* pAcceptContext);
199     virtual bool DoAccept(CPerSocketContextBase* pSocketContext, CPerIOContextBase* pIOContext);
200 
201     virtual bool PostRecv(CPerIOContextBase* pIOContext);
202     virtual bool DoRecv(CPerSocketContextBase* pSocketContext, CPerIOContextBase* pIOContext);
203 
204 protected:
205     virtual bool AssociateIOCP();
206 
207     virtual SOCKET CreateServerSocket();
208     virtual SOCKET BindServerSocket();
209     virtual int ListenServerSocket();
210     virtual bool AcceptConnection(int nPreparation);
211     virtual bool AcceptNewClient(CPerIOContextBase* pAcceptContext);
212     virtual SOCKET CreateClientSocket();
213     virtual bool InitSocketLibrary();
214     virtual bool SetLocalIP();
215 
216 protected:
217     virtual LPFN_ACCEPTEX GetFuncPtrAcceptEx();
218     virtual LPFN_GETACCEPTEXSOCKADDRS GetFuncPtrGetAcceptExSockAddrs();
219 protected:
220     CString m_strServerIP;
221     int m_nPort;
222     struct sockaddr_in m_ServerAddress;
223 
224     CPerSocketContextBase* m_pListenContext;
225 
226     CSITBase* m_pSIT;
227     
228     FuncUserOperation m_funcUserOperation_ACCEPT;
229     FuncUserOperation m_funcUserOperation_RECV;
230     FuncUserOperation m_funcUserOperation_POST;
231 
232     LPFN_ACCEPTEX m_lpfnAcceptEx;
233     LPFN_GETACCEPTEXSOCKADDRS m_lpfnGetAcceptExSockAddrs;
234 };

实现文件

  1 #include "stdafx.h"
  2 #include "SIT.h"
  3 #include "vld.h"
  4 //获得错误文本信息
  5 CString GetLastErrorMessage(DWORD dwLastError)
  6 {
  7     LPTSTR lpMsgBuf = NULL;
  8 
  9     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
 10         NULL,
 11         dwLastError,
 12         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
 13         (LPTSTR)&lpMsgBuf,
 14         0,
 15         NULL);
 16 
 17     CString strMsg(lpMsgBuf);
 18 
 19     LocalFree(lpMsgBuf);
 20 
 21     return strMsg;
 22 }
 23 
 24 bool CSITBase::Init(CIOCPBase* pIOCP, CThreadpoolBase* pThreadpool, CSocketNetBase* pSocketSocket,CSITContextBase* pSITContext)
 25 {
 26     if (pIOCP && pThreadpool && pSocketSocket && pSITContext)
 27     {
 28         m_pIOCP = pIOCP;
 29         m_pThreadpool = pThreadpool;
 30         m_pSocketNet = pSocketSocket;
 31         m_pSITContext = pSITContext;
 32     }
 33     else
 34     {
 35         OutputDebugString(TEXT("CSITBase的Init参数不正确"));
 36 
 37         return false;
 38     }
 39 
 40     return     pSITContext->Init()&&
 41             pIOCP->Init(this)&&
 42             pThreadpool->Init(this) &&
 43             pSocketSocket->Init(this);
 44 
 45 }
 46 
 47 bool CSITBase::AssociateSocketNetWithIOCP(CPerSocketContextBase* pSocketContext)
 48 {
 49     if (GetIOCPObj()!= m_pIOCP->Associate((HANDLE)(pSocketContext->socket), GetIOCPObj(),(ULONG_PTR)pSocketContext))
 50     {
 51         OutputDebugString(TEXT("监听套接字关联IOCP失败: ") + GetLastErrorMessage(GetLastError()) + TEXT("\n"));
 52 
 53         return false;
 54     }
 55 
 56     return true;
 57 }
 58 
 59 bool CSITBase::HandleError(CPerSocketContextBase* pSocketContext, DWORD dwError, DWORD dwThreadID)
 60 {
 61     return    m_pIOCP->HandleError(pSocketContext, dwError, dwThreadID);
 62 }
 63 
 64 bool CSITBase::PostAccept(CPerIOContextBase* pAcceptContext)
 65 {
 66     return m_pSocketNet->PostAccept(pAcceptContext);
 67 }
 68 
 69 bool CSITBase::DoAccept(CPerSocketContextBase* pSocketContext, CPerIOContextBase* pIOContext)
 70 {
 71     return m_pSocketNet->DoAccept(pSocketContext, pIOContext);
 72 }
 73 
 74 bool CSITBase::DoRecv(CPerSocketContextBase* pSocketContext, CPerIOContextBase* pIOContext)
 75 {
 76     return m_pSocketNet->DoRecv(pSocketContext, pIOContext);
 77 }
 78 
 79 void CSITBase::AddSocketContext(CPerSocketContextBase* pSocketContext)
 80 {
 81     m_pSITContext->AddSocketContext(pSocketContext);
 82 }
 83 
 84 void CSITBase::RemoveSocketContext(CPerSocketContextBase* pSocketContext)
 85 {
 86     m_pSITContext->RemoveSocketContext(pSocketContext);
 87 }
 88 
 89 CIOCPBase* CSITBase::GetIOCP()
 90 {
 91     return m_pIOCP;
 92 }
 93 
 94 CSITContextBase* CSITBase::GetSITContext()
 95 {
 96     return m_pSITContext;
 97 }
 98 
 99 CThreadpoolBase* CSITBase::GetThreadpool()
100 {
101     return m_pThreadpool;
102 }
103 
104 CSocketNetBase* CSITBase::GetSocketNet()
105 {
106     return m_pSocketNet;
107 }
108 
109 HANDLE CSITBase::GetIOCPObj()
110 {
111     return m_pIOCP->GetIOCPObj();
112 }
113 
114 CThreadpoolBase::CThreadpoolBase()
115 {
116     m_NumOfThreads = 0;
117     m_phWorkerThreads = NULL;
118     m_pSIT = NULL;
119 }
120 
121 CThreadpoolBase::~CThreadpoolBase()
122 {
123     for (int i = 0; i < m_NumOfThreads;i++)
124     {
125         CloseHandle(m_phWorkerThreads[i]);
126     }
127 
128     delete[] m_phWorkerThreads;
129 }
130 
131 bool CThreadpoolBase::Init(CSITBase* pSIT)
132 {
133     if (pSIT->GetIOCP()==NULL)
134     {
135         OutputDebugString(TEXT("SIT缺少IOCP"));
136 
137         return false;
138     }
139 
140     m_pSIT = pSIT;
141 
142     m_NumOfThreads = GetNumOfThreads();
143     if (m_NumOfThreads<0)
144     {
145         OutputDebugString(TEXT("工作者线程数量小于0"));
146 
147         return false;
148     }
149 
150     m_phWorkerThreads = new HANDLE[m_NumOfThreads];
151 
152     for (int i = 0; i < m_NumOfThreads;i++)
153     {
154         PWorkerThreadUnit pWTU = new WorkerThreadUnit;
155         pWTU->pSIT = m_pSIT;
156         m_phWorkerThreads[i] = CreateThread(0, 0, WorkerThread, (LPVOID)pWTU, 0, &(pWTU->dwThreadID));
157     }
158 
159     OutputDebugString(TEXT("线程初始化完毕"));
160 
161     return true;
162 }
163 
164 int CThreadpoolBase::GetNumOfThreads(int nAdjustment /*= 2*/)
165 {
166     SYSTEM_INFO si;
167     GetSystemInfo(&si);
168 
169     return si.dwNumberOfProcessors * 2 + nAdjustment;
170 }
171 
172 DWORD WINAPI CThreadpoolBase::WorkerThread(LPVOID lpParam)
173 {
174     PWorkerThreadUnit pWTU = (PWorkerThreadUnit)lpParam;
175     CSITBase* pSIT = pWTU->pSIT;
176     DWORD dwThreadID = pWTU->dwThreadID;
177 
178     CString strThreadInfo;
179     strThreadInfo.Format(TEXT("工作者线程 %d"), (int)dwThreadID);
180     OutputDebugString(strThreadInfo+TEXT("\n"));
181 
182     BOOL bRes=FALSE;
183     DWORD dwTransfered = 0;
184     CPerSocketContextBase* pSocketContext=NULL;
185     OVERLAPPED* pOverlapped = NULL;
186 
187     while (true)
188     {
189         bRes = GetQueuedCompletionStatus(pSIT->GetIOCPObj(),
190                                             &dwTransfered,
191                                             (PULONG_PTR)&pSocketContext,
192                                             &pOverlapped,
193                                             INFINITE);
194 
195         if ((DWORD)pSocketContext==0)
196         {
197             OutputDebugString(TEXT("收到PostQueuedCompletionStatus调用,要求线程退出\n"));
198             break;
199         }
200 
201         if (!bRes)
202         {
203             DWORD dwError = GetLastError();
204             OutputDebugString(strThreadInfo + CString(TEXT(" 调用GetQueuedCompletionStatus失败,") + GetLastErrorMessage(dwError))+TEXT("\n"));
205 
206             if (!pSIT->HandleError(pSocketContext,dwError,dwThreadID))
207             {
208                 CPerIOContextBase* pIOContext = CONTAINING_RECORD(pOverlapped, CPerIOContextBase, overlapped);
209                 if (ACCEPT_POSTED==pIOContext->operationtype)
210                 {
211                     pSIT->PostAccept(pIOContext);
212                 }
213             }
214 
215             continue;
216         }
217         else
218         {
219             CPerIOContextBase* pIOContext = CONTAINING_RECORD(pOverlapped, CPerIOContextBase, overlapped);
220 
221             CString strTempPort;
222             strTempPort.Format(TEXT("%d"), pSocketContext->socketaddr.sin_port);
223 
224             if (dwTransfered == 0 && (pIOContext->operationtype == SEND_POSTED || pIOContext->operationtype == RECV_POSTED))
225             {
226                 TCHAR szBuf[MAX_PATH];
227                 InetNtop(AF_INET,&pSocketContext->socketaddr.sin_addr,szBuf,MAX_PATH);
228                 CString strIP;
229                 strIP.Format(TEXT("%s"), szBuf);
230                 OutputDebugString(TEXT("客户端断开连接") + strIP + TEXT(":") + strTempPort + TEXT("\n"));
231                 
232                 pSIT->RemoveSocketContext(pSocketContext);
233                 continue;
234             }
235             else
236             {
237                 switch (pIOContext->operationtype)
238                 {
239                     case ACCEPT_POSTED:
240                         {
241                             pSIT->DoAccept(pSocketContext, pIOContext);
242                         }
243                     break;
244                     case RECV_POSTED:
245                         {
246                             pSIT->DoRecv(pSocketContext, pIOContext);
247                         }
248                     break;
249                     case SEND_POSTED:
250                         {
251                             //
252                         }
253                     break;
254                     default:
255                         {
256 
257                         }
258                     break;
259                 }//switch
260             }
261         }
262     }
263 
264     if (lpParam!=NULL)
265     {
266         delete lpParam;
267         lpParam = NULL;
268     }
269 
270     OutputDebugString(strThreadInfo+TEXT(" 退出\n"));
271 
272     return DWORD(0);
273 }
274 
275 bool CIOCPBase::Init(CSITBase* pSIT)
276 {
277     if (pSIT->GetSITContext()==NULL)
278     {
279         OutputDebugString(TEXT("SIT缺少SITContext"));
280         return false;
281     }
282 
283     m_pSIT = pSIT;
284 
285     m_hIOCompletionPort = Create();
286     if (m_hIOCompletionPort == NULL)
287     {
288         OutputDebugString(GetLastErrorMessage(GetLastError()) + TEXT("\n"));
289 
290         return false;
291     }
292 
293     return true;
294 }
295 
296 HANDLE CIOCPBase::Create(int nConcurrentThread /*= 0*/)
297 {
298     return CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, nConcurrentThread);
299 }
300 
301 HANDLE CIOCPBase::Associate(HANDLE hFileHandle, HANDLE ExistingCompletionPort, ULONG_PTR CompletionKey)
302 {
303     return CreateIoCompletionPort((HANDLE)hFileHandle, ExistingCompletionPort, CompletionKey, 0);
304 }
305 
306 HANDLE CIOCPBase::GetIOCPObj()
307 {
308     return m_hIOCompletionPort;
309 }
310 
311 CSITBase* CIOCPBase::GetSIT()
312 {
313     return m_pSIT;
314 }
315 
316 bool CIOCPBase::HandleError(CPerSocketContextBase* pSocketContext, DWORD dwError, DWORD dwThreadID)
317 {
318     CString strThreadID;
319     strThreadID.Format(TEXT("线程 %d "), dwThreadID);
320     if (WAIT_TIMEOUT == dwError)
321     {
322         if (!CSocketNetBase::IsAlive(pSocketContext->socket))
323         {
324             OutputDebugString(strThreadID+TEXT("检测到客户端异常退出!\n"));
325             m_pSIT->GetSITContext()->RemoveSocketContext(pSocketContext);
326 
327             return true;
328         }
329         else
330         {
331             OutputDebugString(strThreadID+TEXT("网络操作超时!重试中...\n"));
332             return true;
333         }
334     }
335     else
336     if (ERROR_NETNAME_DELETED == dwError)
337     {
338         OutputDebugString(strThreadID+TEXT("检测到客户端异常退出!\n"));
339         m_pSIT->RemoveSocketContext(pSocketContext);
340 
341         return true;
342     }
343     else
344     {
345         OutputDebugString(strThreadID+TEXT("IOCP 出错!\n"));
346         return false;
347     }
348 
349     return true;
350 }
351 
352 CPerIOContextBase::CPerIOContextBase()
353 {
354         ZeroMemory(&overlapped, sizeof(overlapped));
355         ZeroMemory(szBuffer, BUFFER_SIZE_MAX);
356         socket = INVALID_SOCKET;
357         wsaBuf.buf = szBuffer;
358         wsaBuf.len = BUFFER_SIZE_MAX;
359         operationtype = NULL_POSTED;
360 }
361 
362 CPerIOContextBase::~CPerIOContextBase()
363 {
364     if (socket!=INVALID_SOCKET)
365     {
366         closesocket(socket);
367         socket = INVALID_SOCKET;
368     }
369 }
370 
371 void CPerIOContextBase::ResetBuffer()
372 {
373     ZeroMemory(szBuffer, BUFFER_SIZE_MAX);
374 }
375 
376 CPerSocketContextBase::CPerSocketContextBase()
377 {
378     socket = INVALID_SOCKET;
379     memset(&socketaddr, 0, sizeof(socketaddr));
380     listPerIOContext.clear();
381 }
382 
383 CPerSocketContextBase::~CPerSocketContextBase()
384 {
385     if (socket!=INVALID_SOCKET)
386     {
387         closesocket(socket);
388         socket = INVALID_SOCKET;
389     }
390 
391     size_t nSize=listPerIOContext.size();
392     for (size_t i = 0; i < nSize; i++)
393     {
394          delete listPerIOContext.front();
395          listPerIOContext.pop_front();
396     }
397 }
398 
399 CPerIOContextBase* CPerSocketContextBase::GetNewPerIOContext()
400 {
401     CPerIOContextBase* pPerIOContext = new  CPerIOContextBase;
402 
403     listPerIOContext.push_back(pPerIOContext);
404 
405     return pPerIOContext;
406 }
407 
408 void CPerSocketContextBase::RemovePerIOContext(CPerIOContextBase* pPerIOContext)
409 {
410     std::list<CPerIOContextBase* >::iterator itBegin=listPerIOContext.begin();
411     std::list<CPerIOContextBase* >::iterator itEnd=listPerIOContext.end();
412     std::list<CPerIOContextBase* >::iterator it;
413     for (it = itBegin; it != itEnd;++it)
414     {
415         if (*it==pPerIOContext)
416         {
417             listPerIOContext.remove(pPerIOContext);
418             delete pPerIOContext;
419             pPerIOContext = NULL;
420 
421             break;
422         }
423     }
424 }
425 
426 bool CSocketNetBase::SetUserOperation(OPERATION_TYPE eOperationType,FuncUserOperation pFunc)
427 {
428     if (!pFunc)
429     {
430         return false;
431     }
432 
433     switch (eOperationType)
434     {
435     case ACCEPT_POSTED:
436         {
437             m_funcUserOperation_ACCEPT = pFunc;
438         }
439         break;
440     case RECV_POSTED:
441         {
442             m_funcUserOperation_RECV = pFunc;
443         }
444         break;
445     case SEND_POSTED:
446     case NULL_POSTED:
447     default:
448         {
449             OutputDebugString(TEXT("SetUserOperation失败"));
450             return false;
451         }
452         break;
453     }
454 
455     return true;
456 }
457 
458 bool CSocketNetBase::IsAlive(SOCKET& s)
459 {
460     int nByteSent = send(s, "", 0, 0);
461     if (nByteSent == -1)
462     {
463         return false;
464     }
465 
466     return true;
467 }
468 
469 CSocketNetBase::CSocketNetBase()
470 {
471     m_nPort = 12345;
472 }
473 
474 bool CSocketNetBase::Init(CSITBase* pSIT)
475 {
476     if (!pSIT)
477     {
478         return false;
479     }
480 
481     m_pSIT = pSIT;
482 
483     if (InitSocketLibrary()==false)
484     {
485         OutputDebugString(TEXT("InitSocketLibrary失败: ") + GetLastErrorMessage(GetLastError()) + TEXT("\n"));
486 
487         return false;
488     }
489     
490     if (SetLocalIP()==false)
491     {
492         OutputDebugString(TEXT("SetLocalIP失败: ") + GetLastErrorMessage(GetLastError()) + TEXT("\n"));
493 
494         return false;
495     }
496 
497     m_pListenContext = new CPerSocketContextBase;
498     if (m_pListenContext==NULL)
499     {
500         return false;
501     }
502 
503     m_pListenContext->socket = CreateServerSocket();
504     if (m_pListenContext->socket==INVALID_SOCKET)
505     {
506         OutputDebugString(TEXT("创建监听套接字失败: ") + GetLastErrorMessage(GetLastError()) + TEXT("\n"));
507 
508         return false;
509     }
510 
511     if (!AssociateIOCP())
512     {
513         OutputDebugString(TEXT("监听套接字关联IOCP失败: ") + GetLastErrorMessage(GetLastError()) + TEXT("\n"));
514 
515         return false;
516     }
517     
518     ZeroMemory((char*)&m_ServerAddress, sizeof(m_ServerAddress));
519     m_ServerAddress.sin_family = AF_INET;
520 
521     int nLen = WideCharToMultiByte(CP_ACP, 0, m_strServerIP, -1, NULL, 0, NULL, NULL);
522     char* psz = new char[nLen];
523     WideCharToMultiByte(CP_ACP, 0, m_strServerIP, -1, psz, nLen, NULL, NULL);
524     InetPton(AF_INET,CString(psz).GetString(),&(m_ServerAddress.sin_addr.s_addr));
525     delete psz;
526     m_ServerAddress.sin_port = htons((u_short)m_nPort);
527 
528     if (SOCKET_ERROR==BindServerSocket())
529     {
530         OutputDebugString(TEXT("绑定服务器套接字失败: ") + GetLastErrorMessage(GetLastError()) + TEXT("\n"));
531         return false;
532     }
533 
534     if (SOCKET_ERROR==ListenServerSocket())
535     {
536         OutputDebugString(TEXT("监听服务器套接字失败: ") + GetLastErrorMessage(GetLastError()) + TEXT("\n"));
537         return false;
538     }
539 
540     if (GetFuncPtrAcceptEx()==NULL)
541     {
542         OutputDebugString(TEXT("获取GetFuncPtrAcceptEx失败: ") + GetLastErrorMessage(GetLastError()) + TEXT("\n"));
543         return false;
544     }
545 
546     if (GetFuncPtrGetAcceptExSockAddrs()==NULL)
547     {
548         OutputDebugString(TEXT("获取GetFuncPtrGetAcceptExSockAddrs失败: ") + GetLastErrorMessage(GetLastError()) + TEXT("\n"));
549         return false;
550     }
551 
552     if (AcceptConnection(10)==false)
553     {
554         return false;
555     }
556 
557     return true;
558 }
559 
560 bool CSocketNetBase::AssociateIOCP()
561 {
562     return m_pSIT->AssociateSocketNetWithIOCP(m_pListenContext);
563 }
564 
565 SOCKET CSocketNetBase::CreateServerSocket()
566 {
567     return WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
568 }
569 
570 SOCKET CSocketNetBase::BindServerSocket()
571 {
572     return bind(m_pListenContext->socket, (struct sockaddr*)&m_ServerAddress, sizeof(m_ServerAddress));
573 }
574 
575 int CSocketNetBase::ListenServerSocket()
576 {
577     return listen(m_pListenContext->socket, SOMAXCONN);
578 }
579 
580 bool CSocketNetBase::AcceptConnection(int nPreparation)
581 {
582     if (nPreparation<10)
583     {
584         nPreparation = 10;
585     }
586 
587     for (int i = 0; i < nPreparation; i++)
588     {
589         CPerIOContextBase* pAcceptContext = m_pListenContext->GetNewPerIOContext();
590         
591         if (PostAccept(pAcceptContext) == false)
592         {
593             m_pListenContext->RemovePerIOContext(pAcceptContext);
594             return false;
595         }
596     }
597 
598     return true;
599 }
600 
601 bool CSocketNetBase::PostAccept(CPerIOContextBase* pAcceptContext)
602 {
603     pAcceptContext->socket = CreateClientSocket();
604     if (pAcceptContext->socket == INVALID_SOCKET)
605     {
606         OutputDebugString(TEXT("创建用于Accept的客户socket失败:") + GetLastErrorMessage(GetLastError()) + TEXT("\n"));
607         return false;
608     }
609 
610     if (AcceptNewClient(pAcceptContext) == false)
611     {
612         if (WSA_IO_PENDING != GetLastError())
613         {
614             return false;
615         }
616     }
617 
618     return true;
619 }
620 
621 bool CSocketNetBase::DoAccept(CPerSocketContextBase* pSocketContext, CPerIOContextBase* pIOContext)
622 {
623     UNREFERENCED_PARAMETER(pSocketContext);
624 
625     SOCKADDR_IN* addrClient = NULL;
626     SOCKADDR_IN* addrLocal = NULL;
627     int nAddrClient = sizeof(SOCKADDR_IN);
628     int nAddrLocal = sizeof(SOCKADDR_IN);
629 
630     m_lpfnGetAcceptExSockAddrs(pIOContext->wsaBuf.buf,
631                                 pIOContext->wsaBuf.len - (sizeof(SOCKADDR_IN) + 16) * 2,
632                                 sizeof(SOCKADDR_IN) + 16,
633                                 sizeof(SOCKADDR_IN) + 16,
634                                 (LPSOCKADDR*)&addrLocal,
635                                 &nAddrLocal,
636                                 (LPSOCKADDR*)&addrClient,
637                                 &nAddrClient);
638     
639     TCHAR szBuf[MAX_PATH];
640     InetNtop(AF_INET, &addrClient->sin_addr, szBuf, MAX_PATH);
641     CString strInfo(szBuf);
642     strInfo.Format(TEXT("%s:%d 连入,附带信息:%s\n"),strInfo , ntohs(addrClient->sin_port), CString(pIOContext->wsaBuf.buf));
643     OutputDebugString(strInfo);
644 
645     if (m_funcUserOperation_ACCEPT)
646     {
647         m_funcUserOperation_ACCEPT((LPVOID)strInfo.GetBuffer(strInfo.GetLength()));
648     }
649 
650     CPerSocketContextBase* pNewSocketContext = new CPerSocketContextBase;
651     pNewSocketContext->socket = pIOContext->socket;
652     memcpy(&(pNewSocketContext->socketaddr), addrClient, sizeof(SOCKADDR_IN));
653 
654     if (false==m_pSIT->AssociateSocketNetWithIOCP(pNewSocketContext))
655     {
656         if (pNewSocketContext!=NULL)
657         {
658             delete pNewSocketContext;
659             pNewSocketContext = NULL;
660 
661             return false;
662         }
663     }
664 
665     CPerIOContextBase* pNewIOContext = pNewSocketContext->GetNewPerIOContext();
666     pNewIOContext->operationtype = RECV_POSTED;
667     pNewIOContext->socket = pNewSocketContext->socket;
668 
669     if (false==PostRecv(pNewIOContext))
670     {
671         pNewSocketContext->RemovePerIOContext(pNewIOContext);
672 
673         return false;
674     }
675 
676     m_pSIT->AddSocketContext(pNewSocketContext);
677 
678     pIOContext->ResetBuffer();
679 
680     PostAccept(pIOContext);
681 
682     return true;
683 }
684 
685 bool CSocketNetBase::PostRecv(CPerIOContextBase* pIOContext)
686 {
687     DWORD dwFlags = 0;
688     DWORD dwBytes = 0;
689 
690     pIOContext->ResetBuffer();
691     pIOContext->operationtype = RECV_POSTED;
692 
693     int nRecv = WSARecv(pIOContext->socket,
694                         &pIOContext->wsaBuf,
695                         1,
696                         &dwBytes,
697                         &dwFlags,
698                         &pIOContext->overlapped,
699                         NULL);
700     if (SOCKET_ERROR == nRecv && WSA_IO_PENDING != WSAGetLastError())
701     {
702         OutputDebugString(TEXT("投递WSARECV失败"));
703         return false;
704     }
705 
706     return true;
707 }
708 
709 bool CSocketNetBase::DoRecv(CPerSocketContextBase* pSocketContext, CPerIOContextBase* pIOContext)
710 {
711     SOCKADDR_IN* clientaddr = &pSocketContext->socketaddr;
712 
713     TCHAR szBuf[MAX_PATH];
714     InetNtop(AF_INET, &clientaddr->sin_addr, szBuf, MAX_PATH);
715     CString strInfo(szBuf);
716     strInfo.Format(TEXT("%s:%d 信息:%s\n"), strInfo, ntohs(clientaddr->sin_port), CString(pIOContext->wsaBuf.buf));
717     OutputDebugString(strInfo);
718 
719     if (m_funcUserOperation_RECV)
720     {
721         m_funcUserOperation_RECV((LPVOID)strInfo.GetBuffer(strInfo.GetLength()));
722     }
723 
724     return PostRecv(pIOContext);
725 }
726 
727 bool CSocketNetBase::AcceptNewClient(CPerIOContextBase* pAcceptContext)
728 {
729     if (pAcceptContext->socket==INVALID_SOCKET)
730     {
731         return false;
732     }
733 
734     DWORD dwBytes = 0;
735     pAcceptContext->operationtype = ACCEPT_POSTED;
736 
737     if (FALSE==m_lpfnAcceptEx(m_pListenContext->socket,
738                                 pAcceptContext->socket,
739                                 pAcceptContext->wsaBuf.buf,
740                                 pAcceptContext->wsaBuf.len - (sizeof(SOCKADDR_IN)+16)*2,
741                                 sizeof(SOCKADDR_IN)+16,
742                                 sizeof(SOCKADDR_IN)+16,
743                                 &dwBytes,
744                                 &(pAcceptContext->overlapped)))
745     {
746         if (WSA_IO_PENDING!=GetLastError())
747         {
748             OutputDebugString(TEXT("Accept客户socket失败:") + GetLastErrorMessage(GetLastError()) + TEXT("\n"));
749             return false;
750         }
751     }
752 
753     return true;
754 }
755 
756 SOCKET CSocketNetBase::CreateClientSocket()
757 {
758     return WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
759 }
760 
761 bool CSocketNetBase::InitSocketLibrary()
762 {
763     WSADATA wsaData;
764     int nResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
765     if (nResult != NO_ERROR)
766     {
767         OutputDebugString(TEXT("InitSocketLib    初始化Winsock2.2 失败!\n"));
768 
769         return false;
770     }
771 
772     return true;
773 }
774 
775 bool CSocketNetBase::SetLocalIP()
776 {
777     //获得主机名
778     char szHostName[MAX_PATH] = { 0 };
779     gethostname(szHostName, MAX_PATH);
780 
781     struct addrinfo aiHints;
782     ZeroMemory(&aiHints, sizeof(aiHints));
783     aiHints.ai_family = AF_INET;
784     aiHints.ai_socktype = SOCK_STREAM;
785     aiHints.ai_protocol = 0;
786     struct addrinfo *aiResult = NULL;
787     struct addrinfo *aiPtr = NULL;
788     DWORD dwRetval=GetAddrInfoA(szHostName, NULL, &aiHints, &aiResult);
789     if (dwRetval!=0)
790     {
791         return false;
792     }
793 
794     for (aiPtr = aiResult; aiPtr != NULL;aiPtr=aiPtr->ai_next)
795     {
796             TCHAR szBuf[MAX_PATH];
797             InetNtop(AF_INET, &(((struct sockaddr_in*)aiResult->ai_addr)->sin_addr), szBuf, MAX_PATH);
798             CString strInfo(szBuf);
799             strInfo.Format(TEXT("%s"), strInfo);
800 
801             m_strServerIP = strInfo;
802             freeaddrinfo(aiResult);
803             return true;
804     }
805 
806     freeaddrinfo(aiResult);
807 
808     return false;
809 }
810 
811 LPFN_ACCEPTEX CSocketNetBase::GetFuncPtrAcceptEx()
812 {
813     GUID GuidAcceptEx = WSAID_ACCEPTEX;
814 
815     DWORD dwBytes = 0;
816     if (SOCKET_ERROR == WSAIoctl(
817         m_pListenContext->socket,
818         SIO_GET_EXTENSION_FUNCTION_POINTER,
819         &GuidAcceptEx,
820         sizeof(GuidAcceptEx),
821         &m_lpfnAcceptEx,
822         sizeof(m_lpfnAcceptEx),
823         &dwBytes,
824         NULL,
825         NULL))
826     {
827         return NULL;
828     }
829 
830     return m_lpfnAcceptEx;
831 }
832 
833 LPFN_GETACCEPTEXSOCKADDRS CSocketNetBase::GetFuncPtrGetAcceptExSockAddrs()
834 {
835     GUID GuidGetAcceptExSockAddrs = WSAID_GETACCEPTEXSOCKADDRS;
836 
837     DWORD dwBytes = 0;
838     // 获取GetAcceptExSockAddrs函数指针,也是同理
839     if (SOCKET_ERROR == WSAIoctl(
840         m_pListenContext->socket,
841         SIO_GET_EXTENSION_FUNCTION_POINTER,
842         &GuidGetAcceptExSockAddrs,
843         sizeof(GuidGetAcceptExSockAddrs),
844         &m_lpfnGetAcceptExSockAddrs,
845         sizeof(m_lpfnGetAcceptExSockAddrs),
846         &dwBytes,
847         NULL,
848         NULL))
849     {
850         return NULL;
851     }
852 
853     return m_lpfnGetAcceptExSockAddrs;
854 }
855 
856 bool CSITContextBase::Init()
857 {
858     InitializeCriticalSection(&m_cs);
859 
860     m_listPerSocketContext.clear();
861 
862     return true;
863 }
864 
865 void CSITContextBase::AddSocketContext(CPerSocketContextBase* pSocketContext)
866 {
867     EnterCriticalSection(&m_cs);
868     m_listPerSocketContext.push_back(pSocketContext);
869     LeaveCriticalSection(&m_cs);
870 }
871 
872 void CSITContextBase::RemoveSocketContext(CPerSocketContextBase* pSocketContext)
873 {
874     EnterCriticalSection(&m_cs);
875     
876     std::list<CPerSocketContextBase* >::iterator itBegin = m_listPerSocketContext.begin();
877     std::list<CPerSocketContextBase* >::iterator itEnd = m_listPerSocketContext.end();
878     std::list<CPerSocketContextBase* >::iterator it;
879     for (it = itBegin; it != itEnd; ++it)
880     {
881         if (*it == pSocketContext)
882         {
883             m_listPerSocketContext.remove(pSocketContext);
884             delete pSocketContext;
885             pSocketContext = NULL;
886 
887             break;
888         }
889     }
890 
891     LeaveCriticalSection(&m_cs);
892 }
893 
894 bool CUserOperationBase::DoAccept(LPVOID pVoid)
895 {
896     OutputDebugString(TEXT("---DoAccept--->"));
897     OutputDebugString(CString((LPWSTR)pVoid));
898     OutputDebugString(TEXT("\n"));
899     return true;
900 }
901 
902 bool CUserOperationBase::DoRecv(LPVOID pVoid)
903 {
904     OutputDebugString(TEXT("---DoRecv--->"));
905     OutputDebugString(CString((LPWSTR)pVoid));
906     OutputDebugString(TEXT("\n"));
907     return true;
908 }
909 
910 bool CUserOperationBase::DoPost(LPVOID pVoid)
911 {
912     UNREFERENCED_PARAMETER(pVoid);
913 
914     return true;
915 }

调用示例

头文件

1 CSITBase* m_pSIT;
2 CIOCPBase* m_pIOCP;
3 CThreadpoolBase* m_pThreadpool;
4 CSocketNetBase* m_pSocketSocket;
5 CSITContextBase* m_pSITContext;

实现文件

 1     m_pSITContext = new CSITContextBase;
 2 
 3     m_pIOCP=new CIOCPBase;
 4     
 5     m_pThreadpool=new CThreadpoolBase;
 6 
 7     m_pSocketSocket=new CSocketNetBase;
 8 
 9     std::shared_ptr<CUserOperationBase> poUserOperation(new CUserOperationBase);
10     m_pSocketSocket->SetUserOperation(ACCEPT_POSTED, std::bind(&CUserOperationBase::DoAccept, poUserOperation,std::placeholders::_1));
11     m_pSocketSocket->SetUserOperation(RECV_POSTED, std::bind(&CUserOperationBase::DoRecv, poUserOperation, std::placeholders::_1));
12 
13     m_pSIT = new CSITBase;
14     m_pSIT->Init(m_pIOCP, m_pThreadpool, m_pSocketSocket, m_pSITContext);