MFC笔记之多线程聊天室
2014-07-18 22:34
260 查看
新手刚接触,跟着孙鑫老师视频一步一步的做。从VC6.0到VS2010好像并不是那么顺利,下面记录下一点收获。
网络编程的一般步骤:
1声明套接字版本(WSAStartup);2创建套接字(socket);3绑定套接字(bind);4发送接收(sendto/recvfrom);5关闭(closesocket)
第1~3步代码如下:
这段代码要写到OnInitDialog()里;其中ms定义为的SOCKET型成员变量。
既然要用到多线程,这里就先插入一点多线程的知识。
其中fun1pro为新线程的入口函数,ppr为传入新线程的参数结构体指针;参数结构体根据需要自行定义。然后是线程函数的实现,里面具体实现socket的接收显示。并且在VS2010中线程函数返回值不能为空,这里我用的DWORD类型;且最好声明成静态成员函数。
这里将接收到的数据存在了buf里,然后加上格式头存在temp里,通过PostMessage将temp作为自定义消息WM_RECV的lParam传递出去。
这里牵扯到自定义消息的定义
还有消息映射
消息函数的声明实现
发送函数做到了一个按钮的响应函数里
这就基本完成了所有代码,但是在默认使用Unicode字符集的VS2010中还是有点小问题的。其中sendto发送了发送缓存两倍的空间,具体在代码中体现。
参考资料:http://blog.163.com/lj_2005/blog/static/458654220115662544227/
网络编程的一般步骤:
1声明套接字版本(WSAStartup);2创建套接字(socket);3绑定套接字(bind);4发送接收(sendto/recvfrom);5关闭(closesocket)
第1~3步代码如下:
CString error; WORD wver; wver=MAKEWORD(1,1); WSAData data; if(0!=WSAStartup(wver,&data)) { error.Format(_T("声明版本失败,错误代码:%d!"),WSAGetLastError()); MessageBox(error); } ms=socket(2,SOCK_DGRAM,0); if(ms==INVALID_SOCKET) { error.Format(_T("创建套接字失败,错误代码:%d!"),WSAGetLastError()); MessageBox(error); } SOCKADDR_IN msaddr; msaddr.sin_family=AF_INET; msaddr.sin_addr.S_un.S_addr=htonl(INADDR_ANY); msaddr.sin_port=htons(6000); int len=sizeof(msaddr); if(SOCKET_ERROR==bind(ms,(SOCKADDR*)&msaddr,len)) { error.Format(_T("绑定套接字失败,错误代码:%d!"),WSAGetLastError()); MessageBox(error); }
这段代码要写到OnInitDialog()里;其中ms定义为的SOCKET型成员变量。
既然要用到多线程,这里就先插入一点多线程的知识。
HANDLE hThread1; hThread1=CreateThread(NULL,0,fun1pro,(LPVOID)ppr,0,NULL); CloseHandle(hThread1);
其中fun1pro为新线程的入口函数,ppr为传入新线程的参数结构体指针;参数结构体根据需要自行定义。然后是线程函数的实现,里面具体实现socket的接收显示。并且在VS2010中线程函数返回值不能为空,这里我用的DWORD类型;且最好声明成静态成员函数。
DWORD WINAPI CMy0712Dlg::fun1pro(LPVOID lpParameter) { SOCKET sock; HWND hw; CString error; sock=((pr*)lpParameter)->s; hw=((pr*)lpParameter)->hs; CString cbuf,tbuf; TCHAR buf[100]={0}; TCHAR temp[120]={0}; CString ttt,sss; SOCKADDR_IN oaddr; int len=sizeof(SOCKADDR); while (TRUE) { int a=recvfrom(sock,(char*)&buf,100,0,(SOCKADDR*)&oaddr,&len); if(SOCKET_ERROR==a) { error.Format(_T("接受失败,错误代码:%d!"),WSAGetLastError()); AfxMessageBox(error); break; } else if(a==0) { error.Format(_T("socket已经关闭!")); AfxMessageBox(error); break; } else { wsprintf(temp,_T("He said: %s"),buf); memset(buf,0,100); sss=_T(""); if(!::PostMessageA(hw,WM_RECV,0,(LPARAM)temp)) { error.Format(_T("消息传递失败,错误代码:%d!"),GetLastError()); AfxMessageBox(error); error.GetLength(); } } } return 0; }
这里将接收到的数据存在了buf里,然后加上格式头存在temp里,通过PostMessage将temp作为自定义消息WM_RECV的lParam传递出去。
这里牵扯到自定义消息的定义
#define WM_RECV WM_USER+1
还有消息映射
ON_MESSAGE(WM_RECV,OnRecv)
消息函数的声明实现
afx_msg LRESULT OnRecv(WPARAM wParam,LPARAM lParam);
LRESULT CMy0712Dlg::OnRecv(WPARAM wParam,LPARAM lParam) { CString cs(((TCHAR*)lParam)); CString temp; GetDlgItemText(IDC_EDIT1,temp); int i=temp.GetLength(); if(i!=0) {temp+="\r\n";} temp+=cs; SetDlgItemText(IDC_EDIT1,temp); return 0; }
发送函数做到了一个按钮的响应函数里
void CMy0712Dlg::OnBnClickedButton2() { // TODO: 在此添加控件通知处理程序代码 CString cs,error,temp; SOCKADDR_IN addr; addr.sin_family=AF_INET; addr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1"); addr.sin_port=htons(6000); int len=sizeof(addr); GetDlgItemText(IDC_EDIT2,cs); int i=sendto(ms,(char*)cs.GetBuffer(cs.GetLength()*2),cs.GetLength()*2+2,0,(SOCKADDR*)&addr,sizeof(SOCKADDR)); if(SOCKET_ERROR==i) { error.Format(_T("数据发送失败,错误代码:%d!"),WSAGetLastError()); MessageBox(error); } cs=_T(""); SetDlgItemText(IDC_EDIT2,cs); }
这就基本完成了所有代码,但是在默认使用Unicode字符集的VS2010中还是有点小问题的。其中sendto发送了发送缓存两倍的空间,具体在代码中体现。
参考资料:http://blog.163.com/lj_2005/blog/static/458654220115662544227/
相关文章推荐
- 孙鑫MFC笔记(15)--多线程和聊天室的创建
- 孙鑫MFC笔记(15)--多线程和聊天室的创建
- 孙鑫VC++视频笔记(15)多线程与聊天室的创建
- 孙鑫VC视频教程笔记之第十五课“多线程与聊天室”
- 孙鑫VC++视频笔记(15)多线程与聊天室的创建
- <MFC笔记>多线程编程之线程的特性
- 孙鑫视频笔记——多线程与聊天室
- MFC多线程开发学习笔记
- 多线程 学习笔记<2> API 与 MFC 下的一些区别
- Java基础知识强化之网络编程笔记05:UDP之多线程实现聊天室案例
- MFC多线程笔记
- 学习笔记:第15课 多线程和聊天室程序
- 孙鑫VC视频教程笔记之第十五课“多线程与聊天室”
- [MFC学习笔记]--lesson15多线程与聊天室程序的设计
- 多线程演示程序(MFC)
- 孙鑫VC++讲座笔记-(4)MFC消息映射机制的剖析
- MFC的凌乱笔记
- MFC数据库操作笔记
- 多线程(4):JT第3章笔记
- 摘录:MFC界面包装类(多线程时成员函数调用的断言失败)