首页 > 代码库 > 基于UDP的MFC聊天程序设计

基于UDP的MFC聊天程序设计

利用MFC创建基于UDP的聊天通信工具很简单,程序是基于MFC的对话框实现的。程序界面如下面所示:


1 概述 

要添加的内容主要主要是发送端和接受端程序,以及最开始对话框程序初始化的时候对套接字的初始化。以及自定义消息WM_RECVDATA

2 接受线程

 其次要注意的是因为接受函数recvfrom是一个阻塞函数,所以要开辟一个线程来专门接受消息。并且要把socket以及窗口句柄hwnd传递给线程的启动函数。

主要代码如下所示:

BOOLCmfcChatDlg::OnInitDialog()
{
         //…..省略以上代码
         // TODO: 在此添加额外的初始化代码
         ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1) )->SetAddress(127,0,0,1);
         InitSocket();
 
         RECVPARAM *pRecvParam = new RECVPARAM;
         pRecvParam->socket = m_socket;
         pRecvParam->hwnd = m_hWnd;
         HANDLE hThread =CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);
         returnTRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}
 
// 创建并且初始化套接字
BOOLCmfcChatDlg::InitSocket(void)
{
         m_socket =socket(AF_INET,SOCK_DGRAM,0);
         if(INVALID_SOCKET == m_socket)
         {
                   MessageBox(TEXT("socket create failed"));
                   returnFALSE;
         }
        
         sockaddr_in addrSock;
         addrSock.sin_family = AF_INET;
         addrSock.sin_port = htons(6000);
         addrSock.sin_addr.S_un.S_addr =htonl(INADDR_ANY);
 
         intretVal;
         retVal =bind(m_socket,(sockaddr*)&addrSock,sizeof(addrSock));
         if(SOCKET_ERROR == retVal)
         {
                   closesocket(m_socket);
                   MessageBox(TEXT("Faild bind socket"));
                   returnFALSE;
         }
 
         returnTRUE;
}
 
 
 
DWORDCmfcChatDlg::RecvProc(LPVOID lpParameter)
{
         SOCKET socket =((RECVPARAM*)lpParameter)->socket;
         HWND hwnd =((RECVPARAM*)lpParameter)->hwnd;
         deletelpParameter;
         lpParameter = NULL;
 
         sockaddr_in addrFrom;
         int len= sizeof(addrFrom);
 
         charrecvBuf[200];
         chartempBuf[300];
         intretVal;
         while(TRUE)
         {
                   retVal =recvfrom(socket,recvBuf,200,0,(sockaddr*)&addrFrom,&len);
                   if(retVal == SOCKET_ERROR)
                   {
                            break;
                   }
                   sprintf(tempBuf,TEXT("%s say: %s"),inet_ntoa(addrFrom.sin_addr),recvBuf);
                   ::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);
         }
         return0;
}
 
 
afx_msg LRESULTCmfcChatDlg::OnRecvdata(WPARAM wParam, LPARAM lParam)
{
         CString str = (char*)lParam;
         CString strTemp;
        
         GetDlgItemText(IDC_EDIT_RECV,strTemp);
         str += "\r\n";
         strTemp += str;
         SetDlgItemText(IDC_EDIT_RECV,strTemp);
 
         return0;
}
 
 
void CmfcChatDlg::OnBnClickedBtnSend()
{
         // TODO: 在此添加控件通知处理程序代码
         DWORD dwIP;
         ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1) )->GetAddress(dwIP);
 
         sockaddr_in addrTo;
         addrTo.sin_family = AF_INET;
         addrTo.sin_port = htons(6000);
         addrTo.sin_addr.S_un.S_addr =htonl(dwIP);
 
         CString strSend;
         CString strTemp;
         GetDlgItemText(IDC_EDIT_SEND,strSend);
 
         GetDlgItemText(IDC_EDIT_RECV,strTemp);
         strTemp = strTemp + TEXT("you say :") + strSend + "\r\n";
         SetDlgItemText(IDC_EDIT_RECV,strTemp);
        
         CString strIP =inet_ntoa(addrTo.sin_addr);
         if(strIP != CString("127.0.0.1"))
         {
                   sendto(m_socket,strSend,strlen(strSend)+1,0,(sockaddr*)&addrTo,sizeof(sockaddr));
         }
        
         SetDlgItemText(IDC_EDIT_SEND,TEXT("") );
 
}

3 自定义消息添加

在MFC类向导中,消息,添加自定义消息,打开了对话然后添加自定义消息然后在头文件中为自定义消息指定一个值,这个用宏定义来实现,如:define  WM_XXX  WM_USER+1

 4 防火墙

如果程序要跟外网上的交流沟通,那么首先要知道外网的IP,其次就是要注意防火墙,可以把防火墙关闭,从而使其不阻挡消息的收发。


 

基于UDP的MFC聊天程序设计