/// \brief Handles heartbeat checking once a second. If a client is not heard /// from for at least 1 second, send it a heartbeat message which it /// should send back. If we haven't heard from it in 5s, shut down its /// logging. void LogServerThread::checkHeartBeats(void) { #ifndef NOLOGSERVER qlonglong epoch; // cout << "pre-lock 1" << endl; QMutexLocker lock(&logClientMapMutex); // cout << "pre-lock 2" << endl; QMutexLocker lock2(&logClientToDelMutex); loggingGetTimeStamp(&epoch, NULL); // cout << "msgcount " << msgsSinceHeartbeat << endl; msgsSinceHeartbeat = 0; ClientMap::iterator it = logClientMap.begin(); for( ; it != logClientMap.end(); ++it ) { QString clientId = it.key(); LoggerListItem *logItem = it.value(); qlonglong age = epoch - logItem->epoch; if (age > 5) { logClientToDel.append(clientId); } else { // cout << "age " << age << " " << clientId.toLocal8Bit().constData() << endl; pingClient(clientId); } } #endif }
void SendMessage ( unsigned int clientID, const Message& msg ) { ClientMap::iterator iter = clients.find(clientID); if (iter != clients.end()) { ENetPacket* packet = MessageEncoding::Encode(msg); enet_peer_send(iter->second, 0, packet); } }
void ChopClient (unsigned int clientID) //do not confuse with killClient, this is a harsh disconnect { ClientMap::iterator iter = clients.find(clientID); if (iter != clients.end()) { enet_peer_reset(iter->second); //disconnect now, regardless of what the client does clients.erase(iter); } }
void KillClient ( unsigned int clientID ) //this is the nice disconnect { ClientMap::iterator iter = clients.find(clientID); if (iter != clients.end()) { enet_peer_disconnect_later(iter->second, 0); clients.erase(iter); } }
void Server::disconnectAllClients() { ClientMap clients = mClientList.mClients; ClientMap::iterator it; for(it = clients.begin(); it != clients.end(); ++it) { Client* client = it->second; client->startDisconnect(); mClientList.removeClient(client); } }
Message* GetMessage () { ENetEvent event; if (enet_host_service(serverHost, &event, 0)) { Message* msg = NULL; unsigned int clientID = 0; for (ClientMap::iterator iter = clients.begin(); iter != clients.end(); iter++) { if (iter->second == event.peer) { clientID = iter->first; } } switch (event.type) { case ENET_EVENT_TYPE_CONNECT: msg = new Message ( "CONNECT", NULL, 0 ); clientID = nextClientID++; msg->clientID = clientID; clients[clientID] = event.peer; badMessage[clientID][0] = 0; //clear bad-message entry so it can be used Message* keymsg; Message* ivmsg; //make and share encryption keys //ADAM makeBlowKey[clientID]; //ADAM keymsg = new Message( "BLOWKEY", sessionKey[clientID], 16 ); //make a message with the blowkey //ADAM SendMessage( clientID, keymsg ); //send the blowkey //ADAM ivmsg = new Message( "BLOWIV" , sessionIV[clientID], 8 ); //make a message with the blowIV //ADAM SendMessage( clientID, ivmsg ); //send the IV break; case ENET_EVENT_TYPE_DISCONNECT: { msg = new Message ( "DISCONNECT", NULL, 0 ); msg->clientID = clientID; ClientMap::iterator iter = clients.find(clientID); clients.erase(iter); } break; case ENET_EVENT_TYPE_RECEIVE: msg = MessageEncoding::Decode(event.packet); if(msg == NULL) { if (badMessageCount[clientID] >= 4) { KillClient(clientID); } else { BadClient(clientID); } } else { msg->clientID = clientID; /* if( Blowfish::do_decrypt(msg, sessionKey[clientID], sessionIV[clientID]) == false) // msg is passed by reference. Return 0 on error. { //do something with the bad message } else { //do something with the recieved message } */ //disabled until finished implementation } enet_packet_destroy(event.packet); break; } return msg; } return NULL; }
bool IsConnected ( unsigned int clientID ) { return clients.find(clientID) != clients.end(); }
//获取消息队列消息 void proc(void *arg) { HWND hMain = (HWND)arg; USE_JSONCODER_DOC(document); while(1) { Sleep(1); CAutoLock lock(&g_TGetLock); char *msg = NULL; try { msg = reinterpret_cast<char *>(msg_queue.Pop()); //msg = (&doublebuffer_queue)->Popup(); if(!msg) { continue; } } catch(...){ //Log("proc : msg_queue.Pop() fialed."); } #ifdef DEBUG_MODE std::cout << msg << std::endl; #endif //解码 LOAD_JSONCODER_STR(document, msg); JsonCoder jc_decoder; if(!jc_decoder.CheckPacket(document)) { //cout << "error packet" << endl; PostMessage(hMain, WM_ERRORPCK, 0, 0); continue; } //获取消息 uint32 cmd = jc_decoder.GetInt(JC_KEY::JC_MSGTYPE, document); //服务端发送过来的回应包 if(cmd == MESSAGE_TYPE::cmdLoginRep) { //返回的客户列表 std::string user_list = jc_decoder.GetString(JC_KEY::JC_USERLISTREP, document); //上线提示 std::string onlineUser = jc_decoder.GetString(JC_KEY::JC_ONLINEREP, document); //发送上线提醒消息 std::string *olUser = new std::string(onlineUser); PostMessage(hMain, WM_ONLINEWARN, (WPARAM)olUser, 0); #ifdef DEBUG_MODE cout << "user_list" << user_list << endl; #endif //发送列表消息 std::string *uList = new std::string(user_list); //上线的用户提示 std::string *warn = new std::string(onlineUser); PostMessage(hMain, WM_UPDATELIST, (WPARAM)uList, (LPARAM)warn); } else if(cmd == MESSAGE_TYPE::cmdLogoutRep) { //客户端离线提示 std::string logoutUser = jc_decoder.GetString(JC_KEY::JC_LOGOUTUSER, document); //列表删除 ClientMap::iterator ite = cmap.begin(); ite = cmap.find(logoutUser); if(ite != cmap.end()) { cmap.erase(ite); } std::string *ss = new std::string(logoutUser); PostMessage(hMain, WM_DELUSERLIST, (WPARAM)ss, 0); } else if(cmd == MESSAGE_TYPE::cmdPublicMsgRep) { //发送者id std::string user_identify = jc_decoder.GetString(JC_KEY::JC_IDENTIFY, document); //谁发送的 std::string sender = jc_decoder.GetString(JC_KEY::JC_SENDER, document); //发送了什么 std::string pubmsg = jc_decoder.GetString(JC_KEY::JC_PUBMSG, document); //发送时间 std::string pubtime = jc_decoder.GetString(JC_KEY::JC_PUBTIME, document); if(strcmp(user_identify.c_str(), g_Identify.c_str()) != 0) { std::wstring tmp = PublicTool::string2wstring(sender); tmp.append(STR_OTHER_SAY); tmp.append(PublicTool::string2wstring(pubmsg)); tmp.append(L"["); tmp.append(PublicTool::string2wstring(pubtime)); tmp.append(L"]"); std::wstring *ss = new std::wstring(tmp); PostMessage(hMain, WM_PUBMSG, (WPARAM)ss, 0); } } //内存归还到内存池 MsgPool.Release(msg); } }