www.pudn.com > QQ2004_Source_0.01.rar > PeerComm.cpp
#include "stdafx.h" #include "peercomm.h" #includeusing namespace std; #include "XMLParser.h" #include "Communication.h" CPeerComm::CPeerComm(void) { _listenThread = NULL; } CPeerComm::~CPeerComm(void) { } UINT CPeerComm::listenProc(LPVOID wParam) { _ASSERTE(wParam != NULL); if (wParam == NULL) return -1; auto_ptr param((LISTEN_PARAM*)wParam); SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); sockaddr_in addrListen; addrListen.sin_family = AF_INET; addrListen.sin_addr.S_un.S_addr = INADDR_ANY; addrListen.sin_port = 0; int ret = bind(sock, (SOCKADDR*)&addrListen, sizeof(sockaddr_in)); if (ret != 0) { ::closesocket(sock); int error = ::WSAGetLastError(); TRACE("ERROR: Failed to bind the peer listen socket (%d).\n", error); return -1; } while(TRUE) { if (::WaitForSingleObject(*(param->finishEvent), 0) == WAIT_OBJECT_0) { ::closesocket(sock); TRACE("NOTIFY: The peer's listening thread is finished.\n"); ::closesocket(sock); return 0; } DWORD dataLen = 0; ret = ::ioctlsocket(sock, FIONREAD, &dataLen); if (ret != 0) { ::closesocket(sock); int error = ::WSAGetLastError(); TRACE("ERROR: Failed to ioctlsocket() in the peer's listening (%d).\n", error); return -1; } if (dataLen <= 0) { static int count = 0; if (count++ >= 4) { sockaddr_in *addr = &(param->serverAddr); CPeerComm::sendOnlineRequest(sock, param->serverAddr, param->userID); count = 0; sockaddr_in addrBind; int addrLen = sizeof(sockaddr_in); int ret = getsockname(sock, (SOCKADDR*)&addrBind, &addrLen); if (ret != 0) count = 0; } Sleep(500); continue ; } auto_ptr data(new char[dataLen]); sockaddr_in addrFrom; int addrLen = sizeof(sockaddr_in); dataLen = ::recvfrom(sock, data.get(), dataLen, 0, (SOCKADDR*)&addrFrom, &addrLen); if (dataLen == -1) { int error = ::WSAGetLastError(); TRACE("ERROR: Failed to receive the data from peer (%ld).\n", dataLen); continue ; } CElement *root = NULL; CXMLParser parser; if (parser.LoadXML((BYTE*)(data.get()), dataLen) == 0) root = parser.get_root(); if (root == NULL) { TRACE(_T("ERROR: Unknown client message.\n")); continue ; } CString message = root->getChildContent(_T("message")); CString friendID = root->getChildContent(_T("userID")); if (message.IsEmpty() || friendID.IsEmpty()) continue ; TCHAR *szMessage = new TCHAR[message.GetLength() + 1]; TCHAR *szFriendID = new TCHAR[friendID.GetLength() + 1]; _tcscpy(szMessage, message); _tcscpy(szFriendID, friendID); param->wnd->PostMessage(WM_PEER_NOTIFY, (WPARAM)szMessage, (LPARAM)szFriendID); } return -1; } HRESULT CPeerComm::sendMsgToFriend(CString msg, const sockaddr_in &friendAddr, CString userID) { CXMLParser parser; CElement *root = parser.createElement(_T("MESSAGE"), _T("")); root->AddChild(_T("userID"), userID); root->AddChild(_T("message"), msg); parser.set_root(root); if (parser.BuildXML() != 0) return E_FAIL; CString sendOut = parser.get_xml(); CQQSocket sock; if (sock.create(0) != TRUE) return E_FAIL; HRESULT ret = sock.sendToHost((SOCKADDR*)&friendAddr, (BYTE*)((LPCTSTR)sendOut), sendOut.GetLength()); if (ret != S_OK) { AfxMessageBox("·¢ËÍÏûϢʧ°Ü."); return E_FAIL; } return S_OK; } HRESULT CPeerComm::startListen(CWnd *wnd, CString userID, const sockaddr_in &serverAddr) { _ASSERTE(_listenThread == NULL); if (_listenThread != NULL) return E_UNEXPECTED; LISTEN_PARAM *param = new LISTEN_PARAM; param->finishEvent = &_finishEvent; param->wnd = wnd; param->userID = userID; memcpy(¶m->serverAddr, &serverAddr, sizeof(sockaddr_in)); CWinThread *pThread = AfxBeginThread(CPeerComm::listenProc, (LPVOID)param, 0, 0, CREATE_SUSPENDED); _ASSERTE(pThread != NULL); if (pThread == NULL) return E_FAIL; HANDLE hProcess = ::GetCurrentProcess(); BOOL ret = ::DuplicateHandle(hProcess, pThread->m_hThread, hProcess, &_listenThread, 0, TRUE, DUPLICATE_SAME_ACCESS); _ASSERTE(ret != FALSE); if (ret == FALSE) return E_FAIL; pThread->ResumeThread(); return S_OK; } HRESULT CPeerComm::stopListen() { if(_listenThread == NULL) return S_OK; _finishEvent.SetEvent(); DWORD ret = ::WaitForSingleObject(_listenThread, 10000); _ASSERTE(ret == WAIT_OBJECT_0); if (ret != WAIT_OBJECT_0) return E_FAIL; ::CloseHandle(_listenThread); _listenThread = NULL; return S_OK; } HRESULT CPeerComm::sendOnlineRequest(SOCKET sock, const sockaddr_in &serverAddr, LPCTSTR userID) { CXMLParser parser; int addrLen = sizeof(sockaddr_in); sockaddr_in addrSock; int ret = getsockname(sock, (SOCKADDR*)&addrSock, &addrLen); if (ret != 0) { int error = ::WSAGetLastError(); TRACE("ERROR: Failed to get the listen socket port (%d).\n", error); return E_FAIL; } CCommunication comm; if (comm.create() != S_OK) return E_FAIL; if (comm.connect(CQQSocket::IPAddrToString(serverAddr)) != S_OK) return E_FAIL; return comm.sendOnlineRequest(userID, addrSock.sin_port); }