=================================版权声明=================================
版权声明:原创文章 禁止转载
请通过右侧公告中的“联系邮箱(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);