📄 netmsgdlg.cpp
字号:
delete pDeleted;
}
m_cs.Unlock();
}
//##ModelId=3E328B9C004B
UINT CNetMsgDlg::FriendService(LPVOID pNetMsg)
{
//设置计数器,如果计数器不是0, 那么就表明此服务被启动过一次。
//这个服务只能被启动一次。
static long nCounter = 0;
if (nCounter)
return 1;
InterlockedIncrement(&nCounter);
CNetMsgDlg *pDlg = NULL;
if (!pNetMsg)
{
AfxMessageBox(" - FriendService - 应当传入一个有效的 CNetMsgDlg 对象指针!");
TRACE(" - FriendService - 应当传入一个有效的 CNetMsgDlg 对象指针!\n");
ASSERT(FALSE);
}
else
{
pDlg = static_cast<CNetMsgDlg *>(pNetMsg);
}
::CoInitialize(NULL);
TRACE("FriendsService 开始...\n");
CWorkSocket svrSocket;
//
// 1. 使用shortFriendPort来进行接受UDP报文
//
svrSocket.Create(CNetMsgDlg::shortFriendPort, SOCK_DGRAM);
//
// 2. 当收到一个 WM_QUIT 的消息的时候就会退出循环。
//
MSG msg;
char buf[1024];
while(!PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE))
{
#pragma message(" - FriendService - 接受到报文的时候应当验证一下发送端使用的端口是否是 shortFriendPort")
//3. 等候接受报文
CString r_strSourceIP = "";
UINT r_uSourcePort = 0;
#if !defined(_SIMULATE)
int nErr = svrSocket.ReceiveFrom(buf, sizeof(buf), r_strSourceIP, r_uSourcePort);
#else
int nErr = sizeof(DGRAM_FRIEND);
r_strSourceIP = "127.0.0.1";
DGRAM_FRIEND simulateDgm;
simulateDgm.ActionType = ON_LINE;
simulateDgm.NetMsgID = 1002;
strncpy(simulateDgm.NickName, "张三", sizeof(simulateDgm.NickName));
memcpy(buf, &simulateDgm, sizeof(simulateDgm));
#endif
if (SOCKET_ERROR == nErr)
{
TRACE("ReceiveFrom error(0x%x)\n", GetLastError());
}
else if ( 0 == nErr)
{
//远端已经关闭
TRACE(" - FriendsService - 远端已经关闭...\n");
}
else if ( sizeof(DGRAM_FRIEND) == nErr)
{
TRACE(" - FriendsService - 收到朋友报文...\n");
//
//4. 按照报文生成CFriendObj对象
//并且加入动态成员 IPAdress
//
DGRAM_FRIEND newFriend;
memcpy(&newFriend, buf, sizeof(newFriend)); //fill newFriend
CFriendObj *obj = new CFriendObj();
obj->set_IPAddress(r_strSourceIP);
obj->set_NickName(CString(newFriend.NickName));
obj->set_NetMsgID(newFriend.NetMsgID);
obj->set_pDlg(NULL);
//处理这个报文
if (ON_LINE == newFriend.ActionType) //上线报文
pDlg->HandleOnlineDGM(obj);
else if (OFF_LINE == newFriend.ActionType) //下线报文
pDlg->HandleOfflineDGM(obj);
}
//5. 休息5s
Sleep(5000);
TRACE("FriendsService...\n");
}
svrSocket.Close();
TRACE(_T("退出朋友监听线程...\n"));
::CoUninitialize();
AfxEndThread(0);
return 0;
}
//##ModelId=3E328F1D01F9
void CNetMsgDlg::OpenChatDlg(POSITION pos)
{
m_cs.Lock(); //防止在创建窗口的过程之中,朋友链表中的结点被释放。
//1.取得指定的朋友结点
CFriendObj *pObj = m_queueFriends.GetAt(pos);
CChatDlg *pDlg = pObj->get_pDlg();
if (!pDlg)
{
//2.构造这个朋友的聊天窗口
CString strRemoteIPAddress = pObj->get_IPAddress();
CString strRemoteNickName = pObj->get_NickName();
DWORD dwRemoteID = pObj->get_NetMsgID();
pDlg = CChatDlg::CreateFriendRelatedWnd(pos, dwRemoteID, strRemoteNickName, strRemoteIPAddress);
//3.将这个朋友结点和这个刚刚生成的窗口绑定
m_queueFriends.GetAt(pos)->set_pDlg(pDlg);
}
//4.显示这个窗口。
pDlg->ShowWindow(SW_RESTORE);
pDlg->SetForegroundWindow();
m_cs.Unlock();
}
//##ModelId=3E328F930181
bool CNetMsgDlg::Init()
{
bool bRet = false;
try
{
MSXML::IXMLDOMDocumentPtr xmlDoc(__uuidof(MSXML::DOMDocument));
xmlDoc->MSXML::IXMLDOMDocument::async = false; //同步加载XML文件
xmlDoc->MSXML::IXMLDOMDocument::load(".\\conf\\profile.xml");
m_strSelfNickName = (const char *)xmlDoc->MSXML::IXMLDOMDocument::selectSingleNode("NMProfile/NickName")->text;
m_dwSelfNetMsgID = atoi((const char *)xmlDoc->MSXML::IXMLDOMDocument::selectSingleNode("NMProfile/NetMsgID")->text);
bRet = true;
}
catch(_com_error &err)
{
CString strErr = "加载profile.xml失败";
strErr += (const char *)err.Description();
AfxMessageBox(strErr);
}
//Init self friend block
m_profileSelf.ActionType = ON_LINE;
m_profileSelf.NetMsgID = m_dwSelfNetMsgID;
strncpy(m_profileSelf.NickName, m_strSelfNickName, sizeof(m_profileSelf.NickName));
return bRet;
}
//##ModelId=3E32B3E00185
void CNetMsgDlg::OnTimer(UINT nIDEvent)
{
BroadcastOnlineDGM();
CDialog::OnTimer(nIDEvent);
}
//##ModelId=3E32B406022A
CNetMsgDlg::~CNetMsgDlg()
{
}
//##ModelId=3E32B87101C2
short CNetMsgDlg::shortFriendPort;
//##ModelId=3E32BC280043
void CNetMsgDlg::BroadcastFriendDGM(DGRAM_FRIEND dgm)
{
TRACE("BroadcastProfile 开始...\n");
//
// 使用一个UDP的socket
// 并且使用广播方式,请MFC自动选择一个端口。
//
CWorkSocket wrkSocket;
BOOL bErr = wrkSocket.Create(0, SOCK_DGRAM);
if (!bErr)
{
TRACE("wrkSocket.Create error(0x%x)\n", GetLastError());
ASSERT(FALSE);
}
BOOL val = TRUE;
bErr = wrkSocket.SetSockOpt(SO_BROADCAST, &val, sizeof(BOOL));
if (!bErr)
{
TRACE("SetSockOpt error(0x%x)\n", GetLastError());
ASSERT(FALSE);
}
//
// 把自己的profile广播到其他机器的shortFriendPort上去
//
int nErr = wrkSocket.SendTo(&dgm, sizeof(dgm),
CNetMsgDlg::shortFriendPort, NULL);
if (SOCKET_ERROR == nErr)
{
nErr = GetLastError();
TRACE("SendTo error(0x%x)\n", nErr);
}
else
{
//Send OK!!
TRACE("Broadcast profile ok!!\n");
}
wrkSocket.Close();
wrkSocket.ShutDown();
}
//##ModelId=3E32FC9103A1
CFriendObj * CNetMsgDlg::FindFriend(DWORD dwNetMsgID)
{
POSITION pos = m_queueFriends.GetHeadPosition();
CFriendObj *pObj = NULL;
for ( ; pos != NULL; m_queueFriends.GetNext(pos))
{
if (m_queueFriends.GetAt(pos)->get_NetMsgID() == dwNetMsgID)
{
pObj = m_queueFriends.GetAt(pos);
break;
}
}
return pObj;
}
//##ModelId=3E330EFE01CD
void CNetMsgDlg::OnDestroy()
{
KillTimer(PROFILE_TIMER_ID);
//
// 终止朋友、聊天和文件的服务线程
//
if (m_pThreadFriendService)
m_pThreadFriendService->PostThreadMessage(WM_QUIT, 0, 0);
if (m_pThreadChatService)
m_pThreadChatService->PostThreadMessage(WM_QUIT, 0, 0);
if (m_pThreadFileService)
m_pThreadFileService->PostThreadMessage(WM_QUIT, 0, 0);
Sleep(500); //Wait for the threads exit
BroadcastOfflineDGM(); //Tell the others I'am exiting...
POSITION pos = m_queueFriends.GetHeadPosition();
while(pos)
{
delete m_queueFriends.RemoveHead();
pos = m_queueFriends.GetHeadPosition();
}
CDialog::OnDestroy();
}
//##ModelId=3E342F6B02B9
void CNetMsgDlg::OnDblclkListFriends()
{
//
//与指定的对象进行聊天
//
int nIndex = m_listFriends.GetCurSel();
if (LB_ERR == nIndex)
{
AfxMessageBox("请您在选择指定的朋友才能进行聊天!");
}
else
{
OpenChatDlg((POSITION)m_listFriends.GetItemDataPtr(nIndex));
}
}
//##ModelId=3E34420F00D0
void CNetMsgDlg::CloseChatDlg(POSITION pos)
{
m_cs.Lock();
if (NULL != pos)
m_queueFriends.GetAt(pos)->set_pDlg(NULL);
m_cs.Unlock();
}
//##ModelId=3E3573780016
LRESULT CNetMsgDlg::OnChatMsg(WPARAM wParam, LPARAM lParam)
{
CChatDGram *pDGram = (CChatDGram *)lParam;
if (pDGram)
{
//1. 查找这个报文是不是有对应的朋友
CFriendObj *pObj = FindFriend(pDGram->m_dwNetMsgID);
if (pObj)
{
//2.这个朋友结点是不是有聊天窗口。
if (pObj->get_pDlg())
{
//7.交给聊天窗口来处理这个报文。
pObj->get_pDlg()->OnRecv(pDGram->m_strMsg);
}
else
{
TRACE("收到的信息来自%u, 内容是: %s\n"
, pDGram->m_dwNetMsgID
, pDGram->m_strMsg);
}
}
}
delete pDGram;
return 0;
}
//##ModelId=3E361E2402B8
void CNetMsgDlg::OnMenuHistory()
{
#pragma message(" - - - 下面的这个位置,原来被写成是 NULL = m_pChatHistDlg,好玄呀")
if (NULL == m_pChatHistDlg)
{
//1. 创建新窗口。
m_pChatHistDlg = new CFormChatHist();
m_pChatHistDlg->Create(CFormChatHist::IDD);
}
//2. 打开窗口.
m_pChatHistDlg->ShowWindow(SW_SHOW);
}
//##ModelId=3E396F3F0177
const CString& CNetMsgDlg::get_SelfNickName() const
{
return m_strSelfNickName;
}
//##ModelId=3E3971A10142
const DWORD& CNetMsgDlg::get_SelfNetMsgID() const
{
return m_dwSelfNetMsgID;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -