www.gusucode.com > FreeEIM_VC++企业即时通讯软件源代码源码程序 > FreeEIM_VC++企业即时通讯软件源代码源码程序\code\em\EM_UserLogin.cpp
//Download by http://www.NewXing.com // EM_UserLogin.cpp: implementation of the EM_UserLogin class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "stdemdef.h" #include "EM_UserLogin.h" #include "em_userinfo.h" #include "EM_UserTree.h" #include "winsock2.h" #include "../EIM02Dlg.h" // 为了回复登陆信息时不同时发送,采用随机数 #include "stdlib.h" #include "time.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// EM_UserLogin::EM_UserLogin() { m_hBC = NULL; m_hUDP = NULL; } EM_UserLogin::~EM_UserLogin() { Close(); } // 关闭所有线程 void EM_UserLogin::Close() { if (m_hUDP != NULL) { TerminateThread(m_hUDP, 0); CloseHandle(m_hUDP); m_hUDP = NULL; } if (m_hBC != NULL) { TerminateThread(m_hBC, 0); CloseHandle(m_hBC); m_hBC = NULL; } } void EM_UserLogin::Run(EM_UserTree &hTree) { DWORD dwTID1 = 0, dwTID2 = 0; // 创建BC接受线程 m_hBC = CreateThread(NULL, 0, Proc_BC_Recv, &hTree, 0, &dwTID1); // 创建UDP接受线程 m_hUDP = CreateThread(NULL, 0, Proc_UDP_Recv, &hTree, 0, &dwTID2); } // 发送广播登陆消息 void EM_UserLogin::SendLogin_BC(LPEM_DATA msg) { CEIM02Dlg *pDlg = (CEIM02Dlg*)AfxGetMainWnd(); SOCKET m_socket; m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); if (INVALID_SOCKET == m_socket) { MessageBox(0, "socket failed.", NULL, MB_OK); } SOCKADDR_IN sin; sin.sin_addr.s_addr = htonl(INADDR_BROADCAST); sin.sin_family = AF_INET; sin.sin_port = htons(BROADCAST_SEND_PORT); BOOL bOpt = TRUE; if (SOCKET_ERROR == setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, (char*)&bOpt, sizeof(bOpt))) { // Error occurred ::MessageBox(0,"BC setsockopt error.",0,0); return; } char *tmpBuf = msg->GetBuffer(); if (SOCKET_ERROR == sendto(m_socket, tmpBuf, msg->GetLength(), 0, (PSOCKADDR)&sin, sizeof(sin))) { // Error occurred if (pDlg->m_dwStatus == CEIM02Dlg::STATUS_ONLINE) { CString strInfo; strInfo.Format(_T("网络连接失败,%s将自动退出。"), APP_TITLE); pDlg->m_dwStatus = CEIM02Dlg::STATUS_OFFLINE; pDlg->MessageBox(strInfo, _T("网络连接断开"), MB_OK | MB_ICONERROR); pDlg->EM_QuitEIM(); return; } else { // ::MessageBox(0,"STATUS_ONLINE",0,0); return; } } closesocket(m_socket); pDlg->m_dwStatus = CEIM02Dlg::STATUS_ONLINE; } // 发送UDP登陆消息到指定的IP地址 void EM_UserLogin::SendLogin_UDP(LPCTSTR lpszIP) { CEIM02Dlg* pDlg = ((CEIM02Dlg*)AfxGetMainWnd()); srand(time(NULL)); int nTimeToWait = rand() / 1000; Sleep(nTimeToWait); EM_DATA myinfo; myinfo.msg = EM_USERLOGIN; EM_UserInfo eInfo; eInfo.SetDisplayName(pDlg->m_config.m_strDisplayName); eInfo.SetGroupName(pDlg->m_config.m_strGroup); myinfo.len = sizeof(eInfo); myinfo.buf = (char*)&eInfo; SOCKET m_sock; m_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (INVALID_SOCKET == m_sock) { closesocket(m_sock); m_sock = NULL; AfxMessageBox("socket creating error."); return; } SOCKADDR_IN sin; sin.sin_addr.s_addr = inet_addr(lpszIP); sin.sin_family = AF_INET; sin.sin_port = htons(UDP_SEND_PORT); char *tmpBuf = myinfo.GetBuffer(); if (sendto(m_sock, tmpBuf, myinfo.GetLength(), 0, (PSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR) { AfxMessageBox(_T("EM_UserLogin::SendLogin_UDP sendto failed")); return; } closesocket(m_sock); } // 回调函数 DWORD WINAPI EM_UserLogin::Proc_BC_Recv(LPVOID lParam) { CEIM02Dlg* pDlg = ((CEIM02Dlg*)AfxGetMainWnd()); HWND hWnd = pDlg->GetSafeHwnd(); char buf[4096]; char ip[128]; SOCKET sock; sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (INVALID_SOCKET == sock) { AfxMessageBox(_T("socket() error in thread BCReceiver::MsgRecvProc")); return -1; } SOCKADDR_IN sin; sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_family = AF_INET; sin.sin_port = htons(BROADCAST_RECV_PORT); int fromlen = sizeof(sin); if (SOCKET_ERROR == bind(sock, (PSOCKADDR)&sin, fromlen)) { AfxMessageBox(_T("Broadcast receiver bind failed")); return -1; } int recvlen = 0; while (TRUE) { recvlen = recvfrom(sock, buf, 4096, 0, (PSOCKADDR)&sin, &fromlen); // 需要优化 EM_DATA data(buf, recvlen); if (data.msg == EM_USERLOGIN || data.msg == EM_USERLOGOUT || data.msg == EM_USERRENAME || data.msg == EM_USERREGROUP) { FreeEIM_USER *pUser; strcpy(ip, inet_ntoa(sin.sin_addr)); char name[512]; char hostname[128]; char groupname[128]; EM_UserInfo *ui = ((EM_UserInfo*)data.buf); ui->GetDisplayName(name); ui->GetHostName(hostname); ui->GetGroupName(groupname); EM_USERINFO uinfo(strupr(hostname), ip, groupname); if (data.msg == EM_USERLOGIN) { char *tmp = new char[128]; strcpy(tmp, ip); // Add to tree --------------------------------------------------- pDlg->_User_AddNewUser(name, uinfo); // =============================================================== // Reply that i was online.--------------------------------------- pDlg->SendMessage(WM_REPLYBCMSG, (WPARAM)tmp, NULL); // =============================================================== } else if (data.msg == EM_USERLOGOUT) { char *tmp = new char[128]; strcpy(tmp, ip); ::PostMessage(hWnd, WM_USERLOGOUT, (WPARAM)tmp, NULL); // pDlg->_User_DeleteUser(uinfo); } else { // 重新分配内存 pUser = new FreeEIM_USER; if (data.msg == EM_USERRENAME) strcpy(pUser->m_szName, data.buf); else strcpy(pUser->m_szGroup, data.buf); strcpy(pUser->m_szIP, inet_ntoa(sin.sin_addr)); ::PostMessage(hWnd, WM_DESKUPDATEINFO, data.msg, (LPARAM)pUser); } } } return 1; } DWORD WINAPI EM_UserLogin::Proc_UDP_Recv(LPVOID lParam) { CEIM02Dlg* pDlg = ((CEIM02Dlg*)AfxGetMainWnd()); SOCKET s = socket(AF_INET, SOCK_DGRAM, 0); if (s == INVALID_SOCKET) { ::MessageBox(NULL, _T("Socket creating error."), _T("接受线程错误"), MB_OK); return -1; } SOCKADDR_IN sin; sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_family = AF_INET; sin.sin_port = htons(UDP_RECV_MSG_PORT); if (bind(s, (PSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR) { ::MessageBox(NULL, _T("Socket binding error."), _T("接受线程错误"), MB_OK); } SOCKADDR_IN client; int sinLen; int ret; char buf[8192]; char ip[128]; while(1) { sinLen = sizeof(SOCKADDR_IN); if ((ret = recvfrom(s, buf, 8192, 0, (PSOCKADDR)&client, &sinLen)) == SOCKET_ERROR) { ::MessageBox(0,"UDP recvfrom failed.", "Alert", MB_OK); break; } EM_DATA data(buf, ret); if (data.msg == EM_USERLOGIN || data.msg == EM_USERLOGOUT) { strcpy(ip, inet_ntoa(client.sin_addr)); char name[256]; char hostName[256]; char groupName[128]; EM_UserInfo *ui = ((EM_UserInfo*)data.buf); ui->GetDisplayName(name); ui->GetHostName(hostName); ui->GetGroupName(groupName); // Add to tree --------------------------------------------------- EM_USERINFO uinfo(strupr(hostName), ip, groupName); pDlg->_User_AddNewUser(name, uinfo); // =============================================================== } } return 0; } void EM_UserLogin::OnLine() { FreeEIM_User_Logic fLogic; EM_DATA data; data.msg = EM_USERLOGIN; // 登陆 data.buf = (char*)fLogic.GetUserInfo(); data.len = sizeof(EM_UserInfo); SendLogin_BC(& data); } void EM_UserLogin::OffLine() { FreeEIM_User_Logic fLogic; EM_DATA data; data.msg = EM_USERLOGOUT; // 退出 data.buf = (char*)fLogic.GetUserInfo(); data.len = sizeof(EM_UserInfo); SendLogin_BC(&data); } void EM_UserLogin::ReName(LPCTSTR lpszName) { EM_DATA data; data.msg = EM_USERRENAME; // 改名 data.buf = (LPSTR)lpszName; data.len = strlen(lpszName) + 1; SendLogin_BC(&data); } void EM_UserLogin::ReGroup(LPCTSTR lpszGroup) { EM_DATA data; data.msg = EM_USERREGROUP; // 改名 data.buf = (LPSTR)lpszGroup; data.len = strlen(lpszGroup) + 1; SendLogin_BC(&data); }