MFC中多线程创建聊天程序

 

在学习了多线程与套接字的知识,聊天室程序的创建变得也不是那么的困难,这篇文章将讲述到如何采用多线程与套接字创建一个聊天室程序。

开发环境:VC++6.0;

辅助开发工具:MSDN

打开VC++6.0,选择文件—>新建—>MFC AppWizard(exe),创建一个名字为“聊天程序”的对话框框架。拖动控件,为对话框创建一个接收数据的编辑框,一个发送数据的编辑框,一个输入IP地址的控件,一个发送按钮,接收数据编辑框的ID值设为IDC_EDIT_RECEIVE,并将其属性设为多行;发送端的ID值设为IDC_EDIT_SEND;IP地址控件的ID值设为IDC_IPADDRESS1

     框架程序做好了,接下来主要是多线程和套接字的创建,因为该程序采用的是阻塞模式的套接字,如果采用一个线程进行数据的接收和发送,那么当线程去等待接收消息时,这个线程就会一直处于等待状态,最终导致整个程序一直处于等待状态而不能运行,所以接收数据采用另外一个线程完成。

        StdAfx.h中加入#include<Afxsock.h>,InitInstance()函数中加入AfxsockInit()来加载库。为CMyDlg类增加一个BOOL类型的成员函数,名字为InitSock(主要完成套接字的初始化),同时添加一个SOCKET类型的m_socket数据成员,在IninSock成员函数中编写如下代码:

m_socket=socket(AF_INET,SOCK_STREAM,0);
sockaddr_in addr;
addrSock.sin_family=AF_INET;
addrSock.sin_port=htons(5000);
addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));
return TRUE;

        CMyDlg类中的InitDialog()函数中加入刚刚写的InitSock函数进行套接字的初始化;

同时在InitDialog函数中调用CreateThread函数创建一个线程。函数调用方式如下:

CreateThreadNULL,0,SockProc,sock,0,NULL),(该函数中的SockProc参数为这个线程的线程函数,sock是向在这个线程传递参数的指针);这个时候要向该线程传递一个套接字和窗口句柄参数,但是只有一个指针,不能同时传递两个参数,于是在CMyDlg的头文件中自定义一个结构体,如下:

struct recvParam
{SOCKET m_socket1;
HWND hwnd;}; 

InitDialog函数中队结构体中的成员进行赋值,recvParam *pRecvParam=new recvParam;

pRecvParam->m_socket1=m_socket;
pRecvParam->hwnd=m_hWnd;
  同时定义一个线程函数,该函数必须为 static  类型;向 CMyDlg 类增加该函数;向该函数中书写如下代码:

SOCKET sock=(( recvParam *)sock)->sock;
HWND hwnd=(( recvParam *)sock)->hwnd;
delete sock;  
sockaddr_in addrFrom;
int len=sizeof(SOCKADDR);
char recvBuf[200];
char tempBuf[300];
while(TRUE)
{recvfrom(sock,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len);
sprintf(tempBuf,"%s说: %s",inet_ntoa(addrFrom.sin_addr),recvBuf);
::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);
}
return 0;
 

在上面的代码中,有一个WM_RECVDATA消息,这个是我们自己定义的消息,

(自定义WM_RECVDATA的方法,在CMyDlg.h#define  WM_RECVDATA         WM_USER+1   然后在CMyDlg.h中的protect中加入如下代码:afx_msg void OnRecvData(WPARAM wParam,LPARAM lParam);然后再CMyDlg.cpp的消息映射宏中加入       ON_MESSAGE(WM_RECVDATA,OnRecvData),最后自定义该函消息的处理函数如下:

CString str=(char*)lParam;
       CString strtemp;
       GetDlgItemText(IDC_EDIT_RECEIVE,strTemp);
       str+="\r\n";
       str+=strtemp;
       SetDlgItemText(IDC_EDIT_RECV,str);  

     写完了接受数据的代码,接下来处理发送按钮的消息,双击按钮,程序自动为我们添加了消息处理函数,在消息处理  函数中写入如下代码:

       DWORD IP;

       ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(IP);
 
       Sockaddr_in addrTo;
       addrTo.sin_family=AF_INET;
       addrTo.sin_port=htons(5000);
       addrTo.sin_addr.S_un.S_addr=htonl(IP);
 
       CString strSend;
       GetDlgItemText(IDC_EDIT_SEND,strSend);
       sendto(m_socket,strSend,strSend.GetLength()+1,0,
              (SOCKADDR*)&addrTo,sizeof(SOCKADDR));
       SetDlgItemText(IDC_EDIT_SEND,"");
 

最后编译运行,在IP控件上加入对方的IP地址就可以和别人聊天了,程序经过测试,能正常运行。

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值