PeerComm.cpp
上传用户:hysujiao87
上传日期:2007-12-02
资源大小:156k
文件大小:5k
源码类别:

ICQ/即时通讯

开发平台:

C/C++

  1. #include "stdafx.h"
  2. #include "peercomm.h"
  3. #include <memory>
  4. using namespace std;
  5. #include "XMLParser.h"
  6. #include "Communication.h"
  7. CPeerComm::CPeerComm(void)
  8. {
  9. _listenThread = NULL;
  10. }
  11. CPeerComm::~CPeerComm(void)
  12. {
  13. }
  14. UINT CPeerComm::listenProc(LPVOID wParam)
  15. {
  16. _ASSERTE(wParam != NULL);
  17. if (wParam == NULL)
  18. return -1;
  19. auto_ptr<LISTEN_PARAM> param((LISTEN_PARAM*)wParam);
  20. SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
  21. sockaddr_in addrListen;
  22. addrListen.sin_family = AF_INET;
  23. addrListen.sin_addr.S_un.S_addr = INADDR_ANY;
  24. addrListen.sin_port = 0;
  25. int ret = bind(sock, (SOCKADDR*)&addrListen, sizeof(sockaddr_in));
  26. if (ret != 0)
  27. {
  28. ::closesocket(sock);
  29. int error = ::WSAGetLastError();
  30. TRACE("ERROR: Failed to bind the peer listen socket (%d).n", error);
  31. return -1;
  32. }
  33. while(TRUE)
  34. {
  35. if (::WaitForSingleObject(*(param->finishEvent), 0) == WAIT_OBJECT_0)
  36. {
  37. ::closesocket(sock);
  38. TRACE("NOTIFY: The peer's listening thread is finished.n");
  39. ::closesocket(sock);
  40. return 0;
  41. }
  42. DWORD dataLen = 0;
  43. ret = ::ioctlsocket(sock, FIONREAD, &dataLen);
  44. if (ret != 0)
  45. {
  46. ::closesocket(sock);
  47. int error = ::WSAGetLastError();
  48. TRACE("ERROR: Failed to ioctlsocket() in the peer's listening (%d).n", error);
  49. return -1;
  50. }
  51. if (dataLen <= 0)
  52. {
  53. static int count = 0;
  54. if (count++ >= 4)
  55. {
  56. sockaddr_in *addr = &(param->serverAddr);
  57. CPeerComm::sendOnlineRequest(sock, param->serverAddr, param->userID);
  58. count = 0;
  59. sockaddr_in addrBind;
  60. int addrLen = sizeof(sockaddr_in);
  61. int ret = getsockname(sock, (SOCKADDR*)&addrBind, &addrLen);
  62. if (ret != 0)
  63. count = 0;
  64. }
  65. Sleep(500);
  66. continue ;
  67. }
  68. auto_ptr<char> data(new char[dataLen]);
  69. sockaddr_in addrFrom;
  70. int addrLen = sizeof(sockaddr_in);
  71. dataLen = ::recvfrom(sock, data.get(), dataLen, 0, (SOCKADDR*)&addrFrom, &addrLen);
  72. if (dataLen == -1)
  73. {
  74. int error = ::WSAGetLastError();
  75. TRACE("ERROR: Failed to receive the data from peer (%ld).n", dataLen);
  76. continue ;
  77. }
  78. CElement *root = NULL;
  79. CXMLParser parser;
  80. if (parser.LoadXML((BYTE*)(data.get()), dataLen) == 0)
  81. root = parser.get_root();
  82. if (root == NULL)
  83. {
  84. TRACE(_T("ERROR: Unknown client message.n"));
  85. continue ;
  86. }
  87. CString message = root->getChildContent(_T("message"));
  88. CString friendID = root->getChildContent(_T("userID"));
  89. if (message.IsEmpty() || friendID.IsEmpty())
  90. continue ;
  91. TCHAR *szMessage = new TCHAR[message.GetLength() + 1];
  92. TCHAR *szFriendID = new TCHAR[friendID.GetLength() + 1];
  93. _tcscpy(szMessage, message);
  94. _tcscpy(szFriendID, friendID);
  95. param->wnd->PostMessage(WM_PEER_NOTIFY, (WPARAM)szMessage, (LPARAM)szFriendID);
  96. }
  97. return -1;
  98. }
  99. HRESULT CPeerComm::sendMsgToFriend(CString msg, 
  100.    const sockaddr_in &friendAddr, 
  101.    CString userID)
  102. {
  103. CXMLParser parser;
  104. CElement *root = parser.createElement(_T("MESSAGE"), _T(""));
  105. root->AddChild(_T("userID"), userID);
  106. root->AddChild(_T("message"), msg);
  107. parser.set_root(root);
  108. if (parser.BuildXML() != 0)
  109. return E_FAIL;
  110. CString sendOut = parser.get_xml();
  111. CQQSocket sock;
  112. if (sock.create(0) != TRUE)
  113. return E_FAIL;
  114. HRESULT ret = sock.sendToHost((SOCKADDR*)&friendAddr, 
  115. (BYTE*)((LPCTSTR)sendOut), 
  116. sendOut.GetLength());
  117. if (ret != S_OK)
  118. {
  119. AfxMessageBox("发送消息失败.");
  120. return E_FAIL;
  121. }
  122. return S_OK;
  123. }
  124. HRESULT CPeerComm::startListen(CWnd *wnd, CString userID, const sockaddr_in &serverAddr)
  125. {
  126. _ASSERTE(_listenThread == NULL);
  127. if (_listenThread != NULL)
  128. return E_UNEXPECTED;
  129. LISTEN_PARAM *param = new LISTEN_PARAM;
  130. param->finishEvent = &_finishEvent;
  131. param->wnd = wnd;
  132. param->userID = userID;
  133. memcpy(&param->serverAddr, &serverAddr, sizeof(sockaddr_in));
  134. CWinThread *pThread = AfxBeginThread(CPeerComm::listenProc, (LPVOID)param, 0, 0, CREATE_SUSPENDED);
  135. _ASSERTE(pThread != NULL);
  136. if (pThread == NULL)
  137. return E_FAIL;
  138. HANDLE hProcess = ::GetCurrentProcess();
  139. BOOL ret = ::DuplicateHandle(hProcess, 
  140. pThread->m_hThread, 
  141. hProcess, 
  142. &_listenThread, 
  143. 0, 
  144. TRUE, 
  145. DUPLICATE_SAME_ACCESS);
  146. _ASSERTE(ret != FALSE);
  147. if (ret == FALSE)
  148. return E_FAIL;
  149. pThread->ResumeThread();
  150. return S_OK;
  151. }
  152. HRESULT CPeerComm::stopListen()
  153. {
  154. if(_listenThread == NULL)
  155. return S_OK;
  156. _finishEvent.SetEvent();
  157. DWORD ret = ::WaitForSingleObject(_listenThread, 10000);
  158. _ASSERTE(ret == WAIT_OBJECT_0);
  159. if (ret != WAIT_OBJECT_0)
  160. return E_FAIL;
  161. ::CloseHandle(_listenThread);
  162. _listenThread = NULL;
  163. return S_OK;
  164. }
  165. HRESULT CPeerComm::sendOnlineRequest(SOCKET sock, const sockaddr_in &serverAddr, LPCTSTR userID)
  166. {
  167. CXMLParser parser;
  168. int addrLen = sizeof(sockaddr_in);
  169. sockaddr_in addrSock;
  170. int ret = getsockname(sock, (SOCKADDR*)&addrSock, &addrLen);
  171. if (ret != 0)
  172. {
  173. int error = ::WSAGetLastError();
  174. TRACE("ERROR: Failed to get the listen socket port (%d).n", error);
  175. return E_FAIL;
  176. }
  177. CCommunication comm;
  178. if (comm.create() != S_OK)
  179. return E_FAIL;
  180. if (comm.connect(CQQSocket::IPAddrToString(serverAddr)) != S_OK)
  181. return E_FAIL;
  182. return comm.sendOnlineRequest(userID, addrSock.sin_port);
  183. }