⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 netmsgdlg.cpp

📁 本人买的<<VC++项目开发实例>>源代码配套光盘.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		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 + -