多线程聊天室的实现 C++
2012-02-15 22:03
323 查看
使用MFC进行网络编程,实现多线程聊天室
1.MFC网络编程要包含库文件 #include <afxsock.h> ,可以在stdafx.h中包含此文件
2.MFC套接字的初始化可以用AfxSocketInit()这个函数来实现。这个函数可以写在APP类中的initInstance这个函数中。
以下是主要代码实现部分
1.首先编写初始化套接字的函数
////////////////////////////////////////////////////////////////////
//名称:initStocket//
//功能:初始化套接字//
///////////////////////////////////////////////////////////////////
BOOL CUdpChatDlg::initSocket()
{
m_socket=socket(AF_INET,SOCK_DGRAM,0);
if(INVALID_SOCKET==m_socket)
{
MessageBox("套接字创建失败");
return FALSE;
}
SOCKADDR_IN addrSock;
addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(6000);
int retVal;
retVal=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));
if(SOCKET_ERROR==retVal)
{
closesocket(m_socket);
MessageBox(_T("套接字绑定失败"));
return FALSE;
}
return TRUE;
}
这个初始化工作在上一篇文章中具体介绍过,在此不再赘述。
2.在Dlg类中的OnInitDialog类中调用初始化函数,并创建多线程。在OnInitDialog的return TRUE之前加上如下代码
initSocket();
RECVPARAM *pRecvParam=new RECVPARAM;
pRecvParam->hwnd=m_hWnd;
pRecvParam->sock=m_socket;
HANDLE hThread=CreateThread(NULL,0,recvFun,(LPVOID)pRecvParam,0,NULL);//创建多线程
CloseHandle(hThread);
3.创建多线程时的线程函数是recvFun,所以现在应该实现这个函数,具体的代码如下,格式不会写的看前两篇文章,或者自己查阅MSDN的CreateThread也是可以的,具体代码如下
/////////////////////////////////////////////////////////////////////////
//名称:recvFun//
//功能:线程函数,接收聊天信息并将信息处理//
////////////////////////////////////////////////////////////////////////
DWORD WINAPI CUdpChatDlg::recvFun( LPVOID lpParameter)
{
SOCKET sock=((RECVPARAM*)lpParameter)->sock;
HWND hwnd=((RECVPARAM*)lpParameter)->hwnd;//获取套接字与窗口句柄
SOCKADDR_IN addrFrom;
int len=sizeof(SOCKADDR);
char recvBuf[200];
char tempBuf[300];
int retVal;
while(1)
{
retVal=recvfrom(sock,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len);//接收聊天信息
if(SOCKET_ERROR==retVal)//如果信息接收失败,打印错误信息并退出循环
break;
sprintf(tempBuf,"%s says :%s",inet_ntoa(addrFrom.sin_addr),recvBuf);//对接收到的数据进行格式化
//AfxMessageBox(tempBuf);
::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);
/*//////////这里讲解的是如何编写消息响应函数,会写的就直接跳过这些注释
通过传递消息将得到聊天信息传送给对话框控件。消息响应函数的书写需要5步,1.::PostMessage();调用消息传递函数
2.在头文件中定义消息的值,为了避免与以有的消息值重复,可以将消息的值定为 #define WM_RECVDATA WM_USER+1 WM_USER是用户自定义的消息,然后+1避免重复
3.做消息响应函数原型的声明 afx_msg RESULT OnRecvData(WPARAM wParam,LPARAM lParam)
第二步和第三步都是在头文件中做的
4.在CPP文件中做消息映射 ON_MESSAGE(WM_RECVDATA,OnRecvData)最后不要加标点
5.最后是消息响应函数的实现
*/
}
return 0;
}
4.消息响应函数
/////////////////////////////////////////////////////////////////////////
//名称:OnRecvData//
//功能:消息响应函数,将聊天信息显示在编辑框里//
////////////////////////////////////////////////////////////////////////
LRESULT CUdpChatDlg::OnRecvData(WPARAM wParam,LPARAM lParam)
{
CString str=(char*)lParam;
CString strTemp;
GetDlgItemText(IDC_EDIT_MESSAGE,strTemp);
str+="\r\n";
str+=strTemp;
SetDlgItemText(IDC_EDIT_MESSAGE,str);
return TRUE;
}
6.实现发送按钮的功能
/////////////////////////////////////////////////////////////////
//名称:OnBnClickBtnSend()//
//功能:获取IP地址,并发送消息//
////////////////////////////////////////////////////////////////
void CUdpChatDlg::OnBnClickedBtnSend()
{
DWORD dw;
((CIPAddressCtrl*)GetDlgItem(IDC_IP_SEND))->GetAddress(dw);
SOCKADDR_IN addrTo;
addrTo.sin_addr.S_un.S_addr=htonl(dw);
addrTo.sin_family=AF_INET;
addrTo.sin_port=htons(6000);
CString strSend;
GetDlgItemText(IDC_EDIT_SEND,strSend);
sendto(m_socket,(LPCSTR)strSend,strSend.GetLength()+1,0,(SOCKADDR*)&addrTo,sizeof(SOCKADDR));
SetDlgItemText(IDC_EDIT_SEND,"");
}
最后的运行结果如下图所示。步骤可能不是太详细,时间关系,请见谅
1.MFC网络编程要包含库文件 #include <afxsock.h> ,可以在stdafx.h中包含此文件
2.MFC套接字的初始化可以用AfxSocketInit()这个函数来实现。这个函数可以写在APP类中的initInstance这个函数中。
以下是主要代码实现部分
1.首先编写初始化套接字的函数
////////////////////////////////////////////////////////////////////
//名称:initStocket//
//功能:初始化套接字//
///////////////////////////////////////////////////////////////////
BOOL CUdpChatDlg::initSocket()
{
m_socket=socket(AF_INET,SOCK_DGRAM,0);
if(INVALID_SOCKET==m_socket)
{
MessageBox("套接字创建失败");
return FALSE;
}
SOCKADDR_IN addrSock;
addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(6000);
int retVal;
retVal=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));
if(SOCKET_ERROR==retVal)
{
closesocket(m_socket);
MessageBox(_T("套接字绑定失败"));
return FALSE;
}
return TRUE;
}
这个初始化工作在上一篇文章中具体介绍过,在此不再赘述。
2.在Dlg类中的OnInitDialog类中调用初始化函数,并创建多线程。在OnInitDialog的return TRUE之前加上如下代码
initSocket();
RECVPARAM *pRecvParam=new RECVPARAM;
pRecvParam->hwnd=m_hWnd;
pRecvParam->sock=m_socket;
HANDLE hThread=CreateThread(NULL,0,recvFun,(LPVOID)pRecvParam,0,NULL);//创建多线程
CloseHandle(hThread);
3.创建多线程时的线程函数是recvFun,所以现在应该实现这个函数,具体的代码如下,格式不会写的看前两篇文章,或者自己查阅MSDN的CreateThread也是可以的,具体代码如下
/////////////////////////////////////////////////////////////////////////
//名称:recvFun//
//功能:线程函数,接收聊天信息并将信息处理//
////////////////////////////////////////////////////////////////////////
DWORD WINAPI CUdpChatDlg::recvFun( LPVOID lpParameter)
{
SOCKET sock=((RECVPARAM*)lpParameter)->sock;
HWND hwnd=((RECVPARAM*)lpParameter)->hwnd;//获取套接字与窗口句柄
SOCKADDR_IN addrFrom;
int len=sizeof(SOCKADDR);
char recvBuf[200];
char tempBuf[300];
int retVal;
while(1)
{
retVal=recvfrom(sock,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len);//接收聊天信息
if(SOCKET_ERROR==retVal)//如果信息接收失败,打印错误信息并退出循环
break;
sprintf(tempBuf,"%s says :%s",inet_ntoa(addrFrom.sin_addr),recvBuf);//对接收到的数据进行格式化
//AfxMessageBox(tempBuf);
::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);
/*//////////这里讲解的是如何编写消息响应函数,会写的就直接跳过这些注释
通过传递消息将得到聊天信息传送给对话框控件。消息响应函数的书写需要5步,1.::PostMessage();调用消息传递函数
2.在头文件中定义消息的值,为了避免与以有的消息值重复,可以将消息的值定为 #define WM_RECVDATA WM_USER+1 WM_USER是用户自定义的消息,然后+1避免重复
3.做消息响应函数原型的声明 afx_msg RESULT OnRecvData(WPARAM wParam,LPARAM lParam)
第二步和第三步都是在头文件中做的
4.在CPP文件中做消息映射 ON_MESSAGE(WM_RECVDATA,OnRecvData)最后不要加标点
5.最后是消息响应函数的实现
*/
}
return 0;
}
4.消息响应函数
/////////////////////////////////////////////////////////////////////////
//名称:OnRecvData//
//功能:消息响应函数,将聊天信息显示在编辑框里//
////////////////////////////////////////////////////////////////////////
LRESULT CUdpChatDlg::OnRecvData(WPARAM wParam,LPARAM lParam)
{
CString str=(char*)lParam;
CString strTemp;
GetDlgItemText(IDC_EDIT_MESSAGE,strTemp);
str+="\r\n";
str+=strTemp;
SetDlgItemText(IDC_EDIT_MESSAGE,str);
return TRUE;
}
6.实现发送按钮的功能
/////////////////////////////////////////////////////////////////
//名称:OnBnClickBtnSend()//
//功能:获取IP地址,并发送消息//
////////////////////////////////////////////////////////////////
void CUdpChatDlg::OnBnClickedBtnSend()
{
DWORD dw;
((CIPAddressCtrl*)GetDlgItem(IDC_IP_SEND))->GetAddress(dw);
SOCKADDR_IN addrTo;
addrTo.sin_addr.S_un.S_addr=htonl(dw);
addrTo.sin_family=AF_INET;
addrTo.sin_port=htons(6000);
CString strSend;
GetDlgItemText(IDC_EDIT_SEND,strSend);
sendto(m_socket,(LPCSTR)strSend,strSend.GetLength()+1,0,(SOCKADDR*)&addrTo,sizeof(SOCKADDR));
SetDlgItemText(IDC_EDIT_SEND,"");
}
最后的运行结果如下图所示。步骤可能不是太详细,时间关系,请见谅
![](http://hiphotos.baidu.com/%B1%E0%B3%CC%B5%D8%D6%D0%BA%A3/pic/item/370ac65e78f0f7361283a3480a55b319eac413fe.jpg)
相关文章推荐
- Linux平台上用C++实现多线程互斥锁
- c++的对象计数问题的多线程实现
- C++实现多线程全局内存池
- 转 Linux C 网络编程——多线程的聊天室实现(服务器端)
- C++ 实现一个简单的多线程
- 【事件驱动】【数码管识别】(C++多线程实现多幅图像的同步识别)
- C++实现多线程及其三种方法实现多线程同步
- linux下 C++如何实现多线程
- C++最简单的多线程实现
- C++实现内存池MemoryPool 包含单线程和多线程
- c++多线程实现循环打印ABC
- Win32下两种用于C++的线程同步类(多线程实现加锁解锁)
- 基于Linux的消息队列及多线程编程实现的聊天室(一)
- C++:多线程类库的设计与实现(一)
- Win32下两种用于C++的线程同步类(多线程实现加锁解锁)
- 小字典之MFC简单的多线程调用类的成员函数实现逐步画线功能 VS2015 C++ 完成
- C++ 11新特性之用多线程实现生产者消费者问题
- linux下 c++多线程的实现
- udp多线程实现聊天室
- C++ - 多线程的实现