Windows网络编程-简单的多线程聊天室
2016-11-25 22:58
691 查看
实验室系统:Windows10
实验室IDE:VS2012
一、创建MFC文件项目。
文件->新建->项目
然后根据图片进行操作
注意的地方:
1.取消union库
2.勾选上Windows套接字,让系统自动帮我们生成
3.选择Dlog
二、添加控件
点开工具箱
建立两个主框,一个用来接收数据,一个用来发送数据
再在主框里面建立3个edit,一个用来显示发送来的数据,一个用来显示自己发送的数据,下面那个用来显示要发送的数据
最后删掉原有,并加一个按钮为发送,添加一个ip控制
三、编写代码
1.加载套接字数据库
先手到我们的cpp中,因为我们之前选择了Windows套接字库,所以会给我们生成好
我们也可以让系统提示我们是否加载失败
接着我们去查看是包含了头文件
看到这个说明没有问题
然后我们去头文件中去定义。
然后我们去写初始化的函数体
写完了我们的函数,我们需要去设置加载它的地方。
在这个函数中去调用我么的初始化套接字函数
现在开始接收端的程序,为解决CreateThread中的LPVOID只能传递一个参数值的问题,我们首先去头文件穿件一个一个结构体
接下来去定义套接字的指针和串口句柄(现在刚刚调用初始化套接字函数的下面)
为了使用完全使用面向对象的方式,我们去头文件进行定义
然后开始编写Threadpro函数体
很明显发发现M_RECVDATA地方报错,接下来我们就处理这个问题
定义消息的值,在头文件里面写
然后就是去编写发送消息的函数
先去我们的MFC界面双击发送按钮,生成点击事件按钮
并右键属性,去知道我们的显示发送和显示接收数据的ID号
然后我们在去编写消息响应函数
在头文件中写入函数声明
然后去编写消息映射
然后去写函数体
自此,我们代码编写完毕
四、优化控件
1.是显示框分行
右键属性把Multiline设置为true
2.按钮回车发送和不显示按钮
右键按钮属性
五、测试
这里我们使用127.0.0.1回环地址进行测试
这样就说明没有问题了
实验室IDE:VS2012
一、创建MFC文件项目。
文件->新建->项目
然后根据图片进行操作
注意的地方:
1.取消union库
2.勾选上Windows套接字,让系统自动帮我们生成
3.选择Dlog
二、添加控件
点开工具箱
建立两个主框,一个用来接收数据,一个用来发送数据
再在主框里面建立3个edit,一个用来显示发送来的数据,一个用来显示自己发送的数据,下面那个用来显示要发送的数据
最后删掉原有,并加一个按钮为发送,添加一个ip控制
三、编写代码
1.加载套接字数据库
先手到我们的cpp中,因为我们之前选择了Windows套接字库,所以会给我们生成好
我们也可以让系统提示我们是否加载失败
CWinApp::InitInstance(); //去加载套接字库,需要包含一个Afxsock.h的头文件,就不需要去链接套接字库 if (!AfxSocketInit()) { AfxMessageBox("Load socket"); //利用AfxMessageBox弹出提示 return FALSE; }
接着我们去查看是包含了头文件
看到这个说明没有问题
然后我们去头文件中去定义。
然后我们去写初始化的函数体
BOOL CSorgsDlg::InitSocket(){ //套接字本身的初始化 //指定地址族,类型(给予UDT的数据包套接字),0(系统自己选择合适的协议) msocket = socket(AF_INET,SOCK_DGRAM,0);//msocket:私有权限的套接字描述符 if (INVALID_SOCKET == msocket) //判断套接字是否创建失败 { MessageBox("create socket false"); return FALSE; } //作为接收端,需要绑定端口和地址上 SOCKADDR_IN acceptSock; //定义地址结构体的变量 acceptSock.sin_family = AF_INET; //地址族 acceptSock.sin_port = htons(6000);//设定端口 用htons转换 acceptSock.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //接受发送到本地任何IP地址的数据 htonl转换 //进行绑定 int retval = 0; //定义整理变量用来判断 bind(msocket,(SOCKADDR *)&acceptSock,sizeof(SOCKADDR)); if (SOCKET_ERROR == retval) { closesocket(msocket); //关闭套接字 MessageBox("bind false"); return FALSE; } return TRUE; }
写完了我们的函数,我们需要去设置加载它的地方。
在这个函数中去调用我么的初始化套接字函数
BOOL CSorgsChatDlg::OnInitDialog()
现在开始接收端的程序,为解决CreateThread中的LPVOID只能传递一个参数值的问题,我们首先去头文件穿件一个一个结构体
//定义结构体,解决CreateThread中的LPVOID只能传递一个参数值的问题 struct RECVPARAM { SOCKET sock;//定义一个套接字类型的变量 HWND hwnd;//定义一个窗口类型的变量 };
接下来去定义套接字的指针和串口句柄(现在刚刚调用初始化套接字函数的下面)
RECVPARAM *mRecvParam = new RECVPARAM; //定义一个指针 mRecvParam->sock = msocket; //初始化我们创建的套接字 mRecvParam->hwnd = m_hWnd; //初始化我们窗口 mhWnd里面保存了和这个类相关的窗口的句柄 //调用CteateThread常见线程 //NULL,0:和调用线程使用一样的大小,线程函数的地址,(强转)参数,创建的标记(一旦创建立即运行),线程ID HANDLE mThread = CreateThread(NULL,0,Threadpro,(LPVOID)mRecvParam,0,NULL); CloseHandle(mThread); //将线程句柄关闭 同时递减线程类和对象的使用基数
为了使用完全使用面向对象的方式,我们去头文件进行定义
//当创建线程的时候。运行时代码需要去调用这个线程函数从而启动线程 //而我们为了不设置为全局函数设置为CSorgsChatDlg类的成员函数(完全面向对象的思想编程) //而要想调用这个成员函数,必须去定义一个CSorgsChatDlg的对象 //对于运行时代码来说,并不知道要定义那个对象或者说不知道怎么去定义 //所以我们就像这个成员函数设置为静态 static DWORD WINAPI Threadpro(LPVOID mlpvpid); //定义为静态,不属于那一个对象,只属于这个类本身
然后开始编写Threadpro函数体
DWORD WINAPI CSorgsDlg::Threadpro(LPVOID mlpvpid){ //取出传递的来年两个参数值 SOCKET sock = ((RECVPARAM*)mlpvpid)->sock; HWND hwnd = ((RECVPARAM*)mlpvpid)->hwnd; delete mlpvpid; //释放掉内存 //发送数据 SOCKADDR_IN fromSock;//定义套接字地址结构的变量,用来接收发送端的地址信息 int len = sizeof(SOCKADDR);//用来接收返回的地址结构的长度 char acceptBuf[200];//定义字符数组用来接收数据 char tempBuf[300];//定义字符数组用来存放格式化后的数据 int retval; while (true) //不断去接收数据 { retval= recvfrom(sock,acceptBuf,200,0,(SOCKADDR*)&fromSock,&len); //套接字,接收的数据,接收数据长度,标志,地址结构体的指针 if (SOCKET_ERROR == retval) { break; //出错跳出循环 } else //把数据传给对话框 { sprintf_s(tempBuf,"%s说: %s",inet_ntoa(fromSock.sin_addr),recvBuf);//格式化.inet_ntoa()转化为点分十进制字符串 ::PostMessage(hwnd,M_RECVDATA,0,(LPARAM)tempBuf);//数据传给对话框 } } return 0; }
很明显发发现M_RECVDATA地方报错,接下来我们就处理这个问题
定义消息的值,在头文件里面写
然后就是去编写发送消息的函数
先去我们的MFC界面双击发送按钮,生成点击事件按钮
并右键属性,去知道我们的显示发送和显示接收数据的ID号
void CSorgsDlg::OnBnClickedButton1() { DWORD dwIP; ((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP);//IP控件的ID SOCKADDR_IN ToSock;//定义地址结构体变量 ToSock.sin_family = AF_INET; //地址族 ToSock.sin_port = htons(6000);//设定端口 用htons转换 ToSock.sin_addr.S_un.S_addr= htonl(dwIP); CString strSend; GetDlgItemText(IDC_EDIT4,strSend);//发送框里面ID,获取里面的内容 //套接字,发送的buffer,长度(多发送一个字节),标记,地址结构体的指针,地址结构体的长度 sendto(msocket,strSend,strSend.GetLength()+1,0,(SOCKADDR*)&ToSock,sizeof(SOCKADDR));//发送 SetDlgItemText(IDC_EDIT4,"");//发送之后将发送框的内容置空 //显示自己发送框的数据设置 CString strto; GetDlgItemText(IDC_EDIT3,strto);//获取文本,ID号,存放数据的地方 strto +="\r\n"; //增加换行 strto +="帅帅的自己说:"; strto += strSend; SetDlgItemText(IDC_EDIT3,strto);//将数据放回编辑框 }
然后我们在去编写消息响应函数
在头文件中写入函数声明
然后去编写消息映射
然后去写函数体
//消息响应函数 //LRESULT,32位整形数,常常用于回调函数 LRESULT CSorgsDlg::MRecvData(WPARAM wParam,LPARAM lParam){ CString str = (char*)lParam; CString strTemp;//接收久的数据 GetDlgItemText(IDC_EDIT2,strTemp);//获取显示发送框ID号,存放数据的地方 str += "\r\n"; //增加换行 str +=strTemp; SetDlgItemText(IDC_EDIT2,str);//将数据放回编辑框 return TRUE; }
自此,我们代码编写完毕
四、优化控件
1.是显示框分行
右键属性把Multiline设置为true
2.按钮回车发送和不显示按钮
右键按钮属性
五、测试
这里我们使用127.0.0.1回环地址进行测试
这样就说明没有问题了
相关文章推荐
- VC:简单聊天室程序1 --- 多线程编写网络聊天室程序
- Linux socket编程(三) 简单的多线程聊天室
- 网络编程_TCP_Socket通信_聊天室_客户端多线程_群聊JAVA191-192
- Android网络编程之Socket通信实现简单聊天室
- 网络编程_多线程实现聊天室程序
- Linux socket编程(三) 简单的多线程聊天室
- Windows网络编程示例一——简单的echo服务器
- [网络编程]——TCP_Socket通信_聊天室_客户端多线程
- java网络编程——Socket和ServerSocket,套接字编程——简单聊天室
- 网络编程-UDP协议---简单聊天室程序
- Android 网络:基于TCP协议通信,多线程,实现简单的C/S聊天室
- Java网络编程 - 基于UDP协议 实现简单的聊天室程序
- 网络编程(学习整理)---1--(Tcp)实现简单的控制台聊天室
- 基于visual c++之windows核心编程代码分析(59)实现网络简单代理编程
- 网络编程UDP多线程聊天室
- [置顶] 多线程+网络编程实现聊天室
- Linux socket编程(三) 简单的多线程聊天室
- [Windows网络编程课设]南工程聊天室服务器源码
- 网络编程(学习整理)---2--(Udp)实现简单的控制台聊天室
- java多线程以及java网络编程实现简单的聊天系统