读书人

50分线程毒死了,该怎么处理

发布时间: 2012-08-07 14:54:49 作者: rapoo

50分,线程毒死了

C/C++ code
服务器三个线程,1. 第一个线程 分配时接受客户端的数据2. 第二个线程扫描一个map并主动推送用户在线列表的线程,3.第三个线程 检测下线的用户,一旦检测到,则通知服务器界面,让服务器界面去掉该用户,并告知其他用户。客户端检测了 ,没有问题, 我单独写了服务器,可以接收客户端的数据和客户端发送的心跳包。都收到了。但是开启客户端,对服务端调试,则发现很多地方进步了。很是奇怪。大家能帮忙看看 这个三个线程是否存在问题嘛?谢谢了//处理客户端的数据unsigned int CMyServerDlg::ReceiveUserPacke(void*){    while(1)    {        if(WaitForSingleObject(pThis->hKillReceiveEvent,0)==WAIT_OBJECT_0)            return 0;        {            CMutexHelper mtHelp(&mu);            if(pThis->m_pCurSock==NULL)            {                return    0;            }        }        char rcvBuf[500];        memset(rcvBuf,sizeof(rcvBuf),0);        if(SOCKET_ERROR!=pThis->m_pCurSock->Receive(rcvBuf,sizeof(rcvBuf)))        {            //解析            CPacket* pPack=(CPacket*)rcvBuf;            if(pPack->type==CPacket::HeartBeat)        // 心跳包            {                CMutexHelper mtHelp(&mu);                //这里,服务器不做回应,只是简单的更新最后发言时间                std::map<std::string,COnLineUser*>::iterator  iter=pThis->on_line_userMap.find(std::string(pPack->receive_id));                if(iter!=pThis->on_line_userMap.end())                {                    //找到,更新时间                    iter->second->theLastTalkTime=time(NULL);                }            }            else if(pPack->type==CPacket::Verification)        //验证            {                //构建一个在线用户                COnLineUser* ponlineUser=new COnLineUser;                //这里可以去服务器的数据库里查找,是否有该用户,如果有,则。。。。可以完善                memcpy(ponlineUser->UserId,pPack->send_id,sizeof(pPack->send_id));                ponlineUser->theLastTalkTime=time(NULL);            //获取日历时间                CMutexHelper mtHelp(&mu);                ponlineUser->psock=pThis->m_pCurSock;            //这里是浅拷贝                pThis->on_line_userMap.insert(std::make_pair(ponlineUser->UserId,ponlineUser));    //添加到在线用户表中                static std::string strAddUser=ponlineUser->UserId;        //要添加的用户                pThis->PostMessage(WM_USER_LOGIN_ON_OR_OFF,ADD_USER,LPARAM(strAddUser.c_str()));            }            else if(pPack->type==CPacket::Msg)        //消息            {                CMutexHelper mtHelp(&mu);                std::map<std::string,COnLineUser*>::iterator  iter=pThis->on_line_userMap.find(std::string(pPack->receive_id));                if(iter!=pThis->on_line_userMap.end())                {                    //找到,转发出去,并且更新最后发言时间                    iter->second->psock->Send(rcvBuf,sizeof(rcvBuf));                    iter->second->theLastTalkTime=time(NULL);                }                else    //可以告诉用户,发送失败,可以完善该功能                {                }            }        }    }    return 0;}//提示上线用户的线程,开启服务器后就可以创建该线程unsigned int CMyServerDlg::NoiftyUserLogon(void*){    while(1)    {        if(WaitForSingleObject(pThis->hNodifyLogonEvent,0)==WAIT_OBJECT_0)            return    0;        {            CMutexHelper cmHelp(&mu);            //对所有用户发送在线用户列表,构造logon数据包即可            std::map<std::string,COnLineUser*>::iterator iter;            std::map<std::string,COnLineUser*>::iterator iter2;            for(iter=pThis->on_line_userMap.begin();iter!=pThis->on_line_userMap.end();++iter)            {                //构造logon包                CPacket packet;                packet.type=CPacket::SomeOneLogOn;                strcpy(packet.send_id,iter->second->UserId);                for(iter2=pThis->on_line_userMap.begin(); iter2!=pThis->on_line_userMap.end(); ++iter2)                {                    if(iter!=iter2)                    {                        iter2->second->psock->Send(&packet,sizeof(CPacket));                    }                }            }         }        Sleep(NOTIFY_ONLINE_USER_INTEVAL);    }  //end while    return 0;}//提示下线用户线程,检测map,并发消息给界面,让界面删去已经下线的用户,客户断也要删去unsigned int CMyServerDlg::NofityUserLogoff(void*){    static std::string strDeletedUser;        //要删除的用户    while(1)    {        if(WaitForSingleObject(pThis->hNodifyLogoffEvent,0)==WAIT_OBJECT_0)            return 0;        {            CMutexHelper mtHelp(&mu);            std::map<std::string,COnLineUser*>::iterator iter=pThis->on_line_userMap.begin();            while(iter!=pThis->on_line_userMap.end())            {                time_t t=time(NULL);                double time_interval=difftime(t,iter->second->theLastTalkTime);                if(time_interval>TIMEOUT)    //超时,移除该用户                {                    //构造下线包,发给所有用户                    //构造logoff包                    CPacket packet;                    packet.type=CPacket::SomeOneLogOn;                    strcpy(packet.send_id,iter->second->UserId);                    std::map<std::string,COnLineUser*>::iterator iter2=iter;                    for(iter2=pThis->on_line_userMap.begin(); iter2!=pThis->on_line_userMap.end(); ++iter2)                    {                        if(iter!=iter2)                        {                            iter2->second->psock->Send(&packet,sizeof(CPacket));                        }                    }                    //服务器界面上删去下线的用户                    strDeletedUser=iter2->second->UserId;                    pThis->PostMessage(WM_USER_LOGIN_ON_OR_OFF,DELETE_USER,(LPARAM)(strDeletedUser.c_str()));                    ++iter2;                    delete iter->second;                    pThis->on_line_userMap.erase(iter);                //删除该用户                    iter=iter2;                    continue;                }                else                            //更新该用户的最后发言时间                {                    iter->second->theLastTalkTime=t;                    ++iter;                }                    }            //end while        }        Sleep(CHECK_LOGOFF_USER);    }    return 0;} 



[解决办法]
MFC的?
给你看几段我服务端的代码。
我用双向链表存在线列表。

C/C++ code
void CClientSocket::OnReceive(int nErrorCode){    g_cs.Lock();    pWnd = static_cast<CCUPJOINServerDlg*>(AfxGetMainWnd());    Message msg;    Receive(&msg, sizeof(msg));  //得到数据    if (msg.iType == VS_KEEPONLINE)     return; //心跳包,不处理。        if (msg.iSubType == VS_LOGIN)    {        int RecvLogin = pWnd->UserCheck(msg.strName, msg.strPassword);        if (RecvLogin == 1) // normal user            msg.iType = VS_USER;        else if (RecvLogin == 2) // admin user            msg.iType = VS_ADMIN;        else        {            LinkedUser.Delete(LinkedUser.Find(msg.strName));            msg.iType = VS_FAIL;            msg.iSubType = VS_LOGIN;            Send(&msg, sizeof(msg));            return;        }        //CString UserName = msg.strName;        CString strtmp; UINT t;        GetPeerName(strtmp, t);        msg.SetContent(strtmp);        if (CheckBaned(strtmp, msg))        {            msg.iType = VS_FAIL;            msg.iSubType = VS_BANED;            Send(&msg, sizeof(msg));            return;        }        int IsExist = pWnd->CheckRepeatAndKick(msg);        this->SetUserName(msg.strName);        pWnd->m_pClientSocketList.AddTail(this);        //CUP状态        if (pWnd->m_CupApply)            msg.n_UserNum = 1;        else if (pWnd->m_CupStart)            msg.n_UserNum = 2;        else            msg.n_UserNum = 0;        if (IsExist)            pWnd->SendMsg(msg); //给全局发上线消息        else        {            pWnd->SendMsg(msg); //给全局发上线消息            LinkedUser.Append(0, msg.strName);//写在这里添加后,链表里存的UserName不会重复。        }        MakeOnlineList();//发送在线列表        return;    }...} 

读书人网 >C++

热点推荐