升龙物业 老版本 ocx IPO, 加密狗 转值班电话

NetServer.cpp 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #include "StdAfx.h"
  2. #include "NetServer.h"
  3. #include "NetClient.h"
  4. #include "NetLinkMain.h"
  5. CNetServer::CNetServer(CNetLinkMain* pParent) : CSocketBase(pParent), m_lpfnAcceptEx(NULL), m_lpfnGetAcceptExSockAddrs(NULL)
  6. {
  7. }
  8. CNetServer::~CNetServer(void)
  9. {
  10. // 释放掉所有的IO上下文数据
  11. for( int i = 0; i < m_ArrayIoContext.GetCount(); ++i)
  12. {
  13. delete m_ArrayIoContext.GetAt(i);
  14. }
  15. m_ArrayIoContext.RemoveAll();
  16. }
  17. /*****************************************************************
  18. **【函数名称】 __newIoContext
  19. **【函数功能】 创建IoContext用于接收客户端连接
  20. **【参数】
  21. **【返回值】
  22. ****************************************************************/
  23. CNetServer::PPER_IO_CONTEXT CNetServer::__newIoContext( void )
  24. {
  25. PPER_IO_CONTEXT pContext = new PER_IO_CONTEXT;
  26. ASSERT(pContext != NULL);
  27. m_ArrayIoContext.Add( pContext );
  28. return pContext;
  29. }
  30. /*****************************************************************
  31. **【函数名称】 __deleteIoContext
  32. **【函数功能】 删除废弃的IoContext
  33. **【参数】
  34. **【返回值】
  35. ****************************************************************/
  36. void CNetServer::__deleteIoContext( PPER_IO_CONTEXT pIoContext )
  37. {
  38. ASSERT( pIoContext != NULL );
  39. for( int i=0; i<m_ArrayIoContext.GetCount(); ++i )
  40. {
  41. if( pIoContext == m_ArrayIoContext.GetAt(i) )
  42. {
  43. m_ArrayIoContext.RemoveAt(i);
  44. delete pIoContext;
  45. pIoContext = NULL;
  46. break;
  47. }
  48. }
  49. }
  50. /*****************************************************************
  51. **【函数名称】 __postAccept
  52. **【函数功能】 投递Accept请求
  53. **【参数】
  54. **【返回值】
  55. ****************************************************************/
  56. bool CNetServer::__postAccept( PPER_IO_CONTEXT pIoContext )
  57. {
  58. ASSERT( INVALID_SOCKET != m_Socket );
  59. // 准备参数
  60. DWORD dwBytes = 0;
  61. pIoContext->resetBuffer();
  62. WSABUF *pWsaBuf = &pIoContext->m_wsaBuf;
  63. OVERLAPPED *pOl = &pIoContext->m_Overlapped;
  64. // 为以后新连入的客户端先准备好Socket( 这个是与传统accept最大的区别 )
  65. pIoContext->m_sockAccept = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
  66. if( INVALID_SOCKET == pIoContext->m_sockAccept )
  67. return false;
  68. // 投递AcceptEx
  69. if(FALSE == m_lpfnAcceptEx(m_Socket, pIoContext->m_sockAccept, pWsaBuf->buf, 0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16, &dwBytes, pOl))
  70. {
  71. if(WSA_IO_PENDING != WSAGetLastError())
  72. return false;
  73. }
  74. return true;
  75. }
  76. /*****************************************************************
  77. **【函数名称】 doJob
  78. **【函数功能】 开始创建客户端并投递Accept请求
  79. **【参数】
  80. **【返回值】
  81. ****************************************************************/
  82. void CNetServer::doJob( OVERLAPPED* pOverLapped, DWORD BytesTransfered )
  83. {
  84. ASSERT(pOverLapped != NULL);
  85. SOCKADDR_IN* ClientAddr = NULL;
  86. SOCKADDR_IN* LocalAddr = NULL;
  87. int remoteLen = sizeof(SOCKADDR_IN), localLen = sizeof(SOCKADDR_IN);
  88. PER_IO_CONTEXT* pIoContext = CONTAINING_RECORD(pOverLapped, PER_IO_CONTEXT, m_Overlapped);
  89. ASSERT(pIoContext != NULL);
  90. // 1. 首先取得连入客户端的地址信息
  91. m_lpfnGetAcceptExSockAddrs(pIoContext->m_wsaBuf.buf, 0, sizeof(SOCKADDR_IN) + 16, sizeof(SOCKADDR_IN) + 16,
  92. (LPSOCKADDR*)&LocalAddr, &localLen, (LPSOCKADDR*)&ClientAddr, &remoteLen);
  93. // 2. 创建客户端
  94. CNetClient* pClient = new CNetClient(m_pParent, PDU_LINK_TYPE_SERVER, false);
  95. ASSERT(pClient != NULL);
  96. pClient->assoSocket() = pIoContext->m_sockAccept;
  97. pClient->setFarLinkInfo(inet_ntoa(ClientAddr->sin_addr), ntohs(ClientAddr->sin_port));
  98. // 3. 使用完毕之后,投递新的AcceptEx
  99. __postAccept( pIoContext );
  100. // 4. 通知上层新客户端到来
  101. m_pParent->onConnEstablished(pClient);
  102. }
  103. /*****************************************************************
  104. **【函数名称】 create
  105. **【函数功能】 创建
  106. **【参数】
  107. **【返回值】
  108. ****************************************************************/
  109. bool CNetServer::create( int a_ListenPort )
  110. {
  111. m_Socket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
  112. if (INVALID_SOCKET == m_Socket)
  113. return false;
  114. // 将Listen Socket绑定至完成端口中
  115. if(!m_pParent->waitNetEnd(this))
  116. return false;
  117. struct sockaddr_in ServerAddress;
  118. // 填充地址信息
  119. ZeroMemory(&ServerAddress, sizeof(ServerAddress));
  120. ServerAddress.sin_family = AF_INET;
  121. ServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);
  122. ServerAddress.sin_port = htons(a_ListenPort);
  123. // 绑定地址和端口
  124. if (SOCKET_ERROR == bind(m_Socket, (struct sockaddr *) &ServerAddress, sizeof(ServerAddress)))
  125. return false;
  126. // 开始进行监听
  127. if (SOCKET_ERROR == listen(m_Socket, SOMAXCONN))
  128. return false;
  129. // 使用AcceptEx函数,因为这个是属于WinSock2规范之外的微软另外提供的扩展函数
  130. // 所以需要额外获取一下函数的指针
  131. GUID GuidAcceptEx = WSAID_ACCEPTEX;
  132. GUID GuidGetAcceptExSockAddrs = WSAID_GETACCEPTEXSOCKADDRS;
  133. DWORD dwBytes = 0;
  134. if(SOCKET_ERROR == WSAIoctl(m_Socket, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidAcceptEx, sizeof(GuidAcceptEx),
  135. &m_lpfnAcceptEx, sizeof(m_lpfnAcceptEx), &dwBytes, NULL, NULL))
  136. {
  137. return false;
  138. }
  139. // 获取GetAcceptExSockAddrs函数指针,也是同理
  140. if(SOCKET_ERROR == WSAIoctl(m_Socket, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidGetAcceptExSockAddrs, sizeof(GuidGetAcceptExSockAddrs),
  141. &m_lpfnGetAcceptExSockAddrs, sizeof(m_lpfnGetAcceptExSockAddrs), &dwBytes, NULL, NULL))
  142. {
  143. return false;
  144. }
  145. // 为AcceptEx 准备参数,然后投递AcceptEx I/O请求
  146. for( int i = 0; i < MAX_POST_ACCEPT; ++i )
  147. {
  148. PER_IO_CONTEXT* pAcceptIoContext = __newIoContext();
  149. if(!__postAccept(pAcceptIoContext))
  150. {
  151. __deleteIoContext(pAcceptIoContext);
  152. return false;
  153. }
  154. }
  155. return true;
  156. }