PeerComm.cpp
上传用户:hysujiao87
上传日期:2007-12-02
资源大小:156k
文件大小:5k
- #include "stdafx.h"
- #include "peercomm.h"
- #include <memory>
- using 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<LISTEN_PARAM> 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<char> 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);
- }