ServerService.cpp
上传用户:hysujiao87
上传日期:2007-12-02
资源大小:156k
文件大小:13k
- #include "stdafx.h"
- #include "serverservice.h"
- #include "MainFrm.h"
- #include "xmlparser.h"
- #include "QQSocket.h"
- CServerService::CServerService(void)
- {
- _listenThread = NULL;
- _list = NULL;
- }
- CServerService::~CServerService(void)
- {
- }
- HRESULT CServerService::dealLogOnRequest(CXMLParser *request, CElement *responseRoot, CUserList &list)
- {
- DEAL_REQUEST_BEGIN()
- CUserData *userData = list.getUserByID(requestRoot->getChildContent(_T("userID")));
- if (userData != NULL)
- {
- if (requestRoot->getChildContent(_T("password")) != userData->_password)
- userData = NULL;
- }
- if (userData == NULL)
- {
- responseRoot->AddChild(_T("message"), _T("用户名或密码错误."));
- responseRoot->AddChild(_T("result"), _T("1"));
- return S_OK;
- }
- responseRoot->AddChild(_T("result"), _T("0"));
- responseRoot->AddChild(_T("nickname"), userData->_nickname);
- return S_OK;
- }
- HRESULT CServerService::dealLogOffRequest(CXMLParser *request, CElement *responseRoot, CUserList &list)
- {
- DEAL_REQUEST_BEGIN()
- CUserData *userData = list.getUserByID(requestRoot->getChildContent(_T("userID")));
- if (userData != NULL)
- {
- userData->_online = FALSE;
- userData->_lastReport = 0;
- ::ZeroMemory(&userData->_sockAddr, sizeof(sockaddr_in));
- }
- return S_OK;
- }
- HRESULT CServerService::dealRegisterRequest(CXMLParser *request, CElement *responseRoot, CUserList &list)
- {
- DEAL_REQUEST_BEGIN()
- CUserData *userData = list.getUserByID(requestRoot->getChildContent(_T("userID")));
- if (userData != NULL)
- {
- responseRoot->AddChild(_T("result"), _T("1"));
- responseRoot->AddChild(_T("message"), _T("这个ID已经有人使用了."));
- return S_OK;
- }
-
- CUserData newUser;
- newUser._clientID = requestRoot->getChildContent(_T("userID"));
- newUser._password = requestRoot->getChildContent(_T("password"));
- newUser._nickname = requestRoot->getChildContent(_T("nickname"));
- list.addUser(&newUser);
- responseRoot->AddChild(_T("result"), _T("0"));
- return S_OK;
- }
- HRESULT CServerService::dealQueryUserRequest(CXMLParser *request, CElement *responseRoot, CUserList &list)
- {
- DEAL_REQUEST_BEGIN()
- CString userID = requestRoot->getChildContent(_T("userID"));
- CUserData *userData = list.getUserByID(userID);
- if (userData == NULL)
- {
- responseRoot->AddChild(_T("result"), _T("1"));
- }
- else
- {
- responseRoot->AddChild(_T("result"), _T("0"));
- responseRoot->AddChild(_T("userID"), userData->_clientID);
- responseRoot->AddChild(_T("nickname"), userData->_nickname);
- if (userData->_online)
- {
- responseRoot->AddChild(_T("online"), _T("true"));
- responseRoot->AddChild(_T("ipAddr"), CQQSocket::IPAddrToString(userData->_sockAddr));
- CString port;
- port.Format("%d", userData->_sockAddr.sin_port);
- responseRoot->AddChild(_T("port"), port);
- }
- else
- responseRoot->AddChild(_T("online"), _T("false"));
- }
- return S_OK;
- }
- HRESULT CServerService::dealAddFriendRequest(CXMLParser *request, CElement *responseRoot, CUserList &list)
- {
- DEAL_REQUEST_BEGIN()
- CUserData *friendData = list.getUserByID(requestRoot->getChildContent(_T("friendID")));
- if (friendData != NULL)
- {
- CUserData *userData = list.getUserByID(requestRoot->getChildContent(_T("userID")));
- HRESULT ret = userData->addFriend(friendData->_clientID);
- if (ret == S_OK)
- {
- responseRoot->AddChild(_T("result"), _T("0"));
- return S_OK;
- }
- if (ret == S_FALSE)
- {
- responseRoot->AddChild(_T("result"), _T("1"));
- responseRoot->AddChild(_T("message"), _T("该用户已经在好友列表中."));
- return S_OK;
- }
- responseRoot->AddChild(_T("result"), _T("500"));
- responseRoot->AddChild(_T("message"), _T("服务器内部错误."));
- return S_OK;
- }
- responseRoot->AddChild(_T("result"), _T("2"));
- responseRoot->AddChild(_T("message"), _T("该用户不存在."));
- return S_OK;
- }
- HRESULT CServerService::dealDownloadFriendsRequest(CXMLParser *request, CElement *responseRoot, CUserList &list)
- {
- DEAL_REQUEST_BEGIN()
-
- CUserData *userData = list.getUserByID(requestRoot->getChildContent(_T("userID")));
- if (userData != NULL)
- {
- responseRoot->AddChild(_T("result"), _T("0"));
- for (int i = 0; i < userData->getFriendCount(); i++)
- {
- responseRoot->AddChild(_T("friend"), userData->getFriendID(i));
- }
- }
- else
- {
- responseRoot->AddChild(_T("result"), _T("1"));
- responseRoot->AddChild(_T("message"), _T("要查询好友的用户不存在."));
- }
- return S_OK;
- }
- HRESULT CServerService::dealOnlineRequest(CXMLParser *request, CElement *responseRoot, const sockaddr_in& addrFrom, CUserList &list)
- {
- DEAL_REQUEST_BEGIN()
- CUserData *friendData = list.getUserByID(requestRoot->getChildContent(_T("userID")));
- if (friendData != NULL)
- {
- CString csPort = requestRoot->getChildContent(_T("port"));
- short port = _ttoi(csPort);
- memcpy(&friendData->_sockAddr, &addrFrom, sizeof(sockaddr_in));
- friendData->_sockAddr.sin_port = port;
- friendData->_lastReport = ::GetTickCount();
- friendData->_online = TRUE;
- }
- return S_OK;
- }
- HRESULT CServerService::dealRequest(BYTE *data,
- int dataLen,
- const SOCKET &sock,
- const sockaddr_in &addrFrom,
- CUserList* list)
- {
- _ASSERTE(data != NULL);
- if (data == NULL)
- return E_INVALIDARG;
- CXMLParser request;
- if (request.LoadXML(data, dataLen) != 0)
- return E_FAIL;
- CElement *requestRoot = request.get_root();
- _ASSERTE(requestRoot->get_tag() == _T("REQUEST"));
-
- CElement *type = requestRoot->GetFirstChildByTag(_T("type"));
- _ASSERTE(type != NULL);
- if (type == NULL)
- return E_FAIL;
-
- if (type->get_content() != _T("ONLINE"))
- {
- CString log = logMessage(&request, addrFrom);
- TCHAR *msg = new TCHAR[log.GetLength() + 1];
- _tcscpy(msg, log);
- AfxGetMainWnd()->PostMessage(WM_SERVICE_NOTIFY, (WPARAM)msg, 0);
- }
- CXMLParser response;
- CElement *responseRoot = response.createElement(_T("RESPONSE"), _T(""));
-
- // Add the new request deal code here.
- if (type->get_content() == _T("LOGON"))
- {
- HRESULT ret = dealLogOnRequest(&request, responseRoot, *list);
- if (ret != S_OK)
- {
- delete responseRoot;
- return ret;
- }
- }
- if (type->get_content() == _T("REGISTER"))
- {
- HRESULT ret = dealRegisterRequest(&request, responseRoot, *list);
- if (ret != S_OK)
- {
- delete responseRoot;
- return ret;
- }
- }
- if (type->get_content() == _T("ADDFRIEND"))
- {
- HRESULT ret = dealAddFriendRequest(&request, responseRoot, *list);
- if (ret != S_OK)
- {
- delete responseRoot;
- return ret;
- }
- }
- if (type->get_content() == _T("DOWNLOADFRIENDS"))
- {
- HRESULT ret = dealDownloadFriendsRequest(&request, responseRoot, *list);
- if (ret != S_OK)
- {
- delete responseRoot;
- return ret;
- }
- }
- if (type->get_content() == _T("QUERYUSER"))
- {
- HRESULT ret = dealQueryUserRequest(&request, responseRoot, *list);
- if (ret != S_OK)
- {
- delete responseRoot;
- return ret;
- }
- }
- if (type->get_content() == _T("ONLINE"))
- {
- dealOnlineRequest(&request, responseRoot, addrFrom, *list);
- delete responseRoot;
- return S_OK;
- }
- if (type->get_content() == _T("LOGOFF"))
- {
- dealLogOffRequest(&request, responseRoot, *list);
- delete responseRoot;
- return S_OK;
- }
- // End of adding request deal code.
- response.set_root(responseRoot);
- if (response.BuildXML() != 0)
- {
- TRACE("ERROR: Failed to build the response xml.n");
- return E_FAIL;
- }
- CString xml = response.get_xml();
- int ret = send(sock, ((LPCTSTR)xml), xml.GetLength() * sizeof(TCHAR), 0);
- if (ret == SOCKET_ERROR)
- return E_FAIL;
- return S_OK;
- }
- UINT CServerService::serviceProc(LPVOID wParam)
- {
- auto_ptr<LISTEN_PARAM> param((LISTEN_PARAM*)wParam);
- SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
- sockaddr_in addrListen;
- addrListen.sin_family = AF_INET;
- addrListen.sin_addr.S_un.S_addr = INADDR_ANY;
- addrListen.sin_port = htons(6000);
- int ret = bind(sock, (SOCKADDR*)&addrListen, sizeof(sockaddr_in));
- if (ret != 0)
- {
- ::closesocket(sock);
- int error = ::WSAGetLastError();
- TRACE("ERROR: Failed to bind the server listen socket (%d).n", error);
- return -1;
- }
- ret = listen(sock, 5);
- if (ret != 0)
- {
- ::closesocket(sock);
- int error = ::WSAGetLastError();
- TRACE("ERROR: Failed to listen the server listen socket (%d).n", error);
- return -1;
- }
- u_long arg = TRUE;
- ret = ioctlsocket(sock, FIONBIO, &arg);
- if (ret != 0)
- {
- ::closesocket(sock);
- int error = ::WSAGetLastError();
- TRACE("ERROR: Failed to ioctlsocket the socket to non-blocking mode (%d).n", error);
- return -1;
- }
- while(TRUE)
- {
- while(TRUE)
- {
- if (::WaitForSingleObject(*(param->finishEvent), 0) == WAIT_OBJECT_0)
- {
- ::closesocket(sock);
- TRACE("NOTIFY: The server's listening thread is finished.n");
- return 0;
- }
- fd_set readset;
- FD_ZERO(&readset);
- FD_SET(sock, &readset);
- TIMEVAL time;
- time.tv_sec = 0;
- time.tv_usec = 1;
- int ret = select(0, &readset, NULL, NULL, &time);
- if (ret == SOCKET_ERROR)
- {
- ::closesocket(sock);
- int error = ::WSAGetLastError();
- TRACE("ERROR: Failed to select the socket states (%d).n", error);
- return -1;
- }
- if (ret != 0)
- break ;
- }
- sockaddr_in addrFrom;
- ::ZeroMemory(&addrFrom, sizeof(sockaddr_in));
- int addrLen = sizeof(sockaddr_in);
- SOCKET acceptedSock = accept(sock, (SOCKADDR*)&addrFrom, &addrLen);
- _ASSERTE(acceptedSock != INVALID_SOCKET);
- if (acceptedSock == INVALID_SOCKET)
- {
- ::closesocket(sock);
- int error = ::WSAGetLastError();
- TRACE("ERROR: Failed to accept a connect (%d).n", error);
- return -1;
- }
- u_long arg = FALSE;
- ret = ioctlsocket(acceptedSock, FIONBIO, &arg);
- if (ret != 0)
- {
- ::closesocket(acceptedSock);
- ::closesocket(sock);
- int error = ::WSAGetLastError();
- TRACE("ERROR: Failed to ioctlsocket the socket to non-blocking mode (%d).n", error);
- return -1;
- }
-
- while(TRUE)
- {
- if (::WaitForSingleObject(*(param->finishEvent), 0) == WAIT_OBJECT_0)
- {
- ::closesocket(acceptedSock);
- ::closesocket(sock);
- TRACE("NOTIFY: The server's listening thread is finished.n");
- return 0;
- }
- DWORD dataLen = 0;
- ret = ::ioctlsocket(acceptedSock, FIONREAD, &dataLen);
- if (ret != 0)
- {
- ::closesocket(acceptedSock);
- ::closesocket(sock);
- int error = ::WSAGetLastError();
- TRACE("ERROR: Failed to ioctlsocket() on the accepted socket (%d).n", error);
- return -1;
- }
- if (dataLen <= 0)
- {
- Sleep(50);
- continue ;
- }
- auto_ptr<BYTE> data(new BYTE[dataLen]);
- dataLen = recv(acceptedSock, (char*)(data.get()), dataLen, 0);
- if (dataLen == SOCKET_ERROR)
- {
- ::closesocket(acceptedSock);
- ::closesocket(sock);
- int error = ::WSAGetLastError();
- TRACE("ERROR: Failed to receive the request (%d).n", error);
- return -1;
- }
-
- dealRequest(data.get(), dataLen, acceptedSock, addrFrom, param->list);
- break ;
- }
- closesocket(acceptedSock);
- }
- return -1;
- }
- HRESULT CServerService::startListen(CUserList *list)
- {
- _ASSERTE(_listenThread == NULL);
- if (_listenThread != NULL)
- return E_UNEXPECTED;
- _list = list;
- LISTEN_PARAM *param = new LISTEN_PARAM;
- param->finishEvent = &_finishEvent;
- param->list = list;
- CWinThread *pThread = AfxBeginThread(CServerService::serviceProc, (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 CServerService::stopListen()
- {
- if(_listenThread == NULL)
- return S_OK;
- _finishEvent.SetEvent();
- DWORD ret = ::WaitForSingleObject(_listenThread, 5000);
- _ASSERTE(ret == WAIT_OBJECT_0);
- if (ret != WAIT_OBJECT_0)
- return E_FAIL;
- ::CloseHandle(_listenThread);
- _listenThread = NULL;
- return S_OK;
- }
- CString CServerService::logMessage(CXMLParser *msg, const sockaddr_in &addrFrom)
- {
- CString notifyMsg = _T("Received a request from ");
- notifyMsg += CQQSocket::IPAddrToString(addrFrom);
- CElementList list;
- msg->get_root()->GetChildrenByTag(NULL, list);
- POSITION pos = list.GetHeadPosition();
- while(pos != NULL)
- {
- CElement *element = list.GetNext(pos);
- _ASSERTE(element != NULL);
- if (element == NULL)
- return _T("");
- CString csElement;
- csElement.Format(" %s=%s", element->get_tag(), element->get_content());
- notifyMsg += csElement;
- }
- return notifyMsg;
- }