网络聊天程序

  • 格式:doc
  • 大小:545.50 KB
  • 文档页数:10

部分程序代码一、消息的发送设置void CChatDlg::OnBtnSend(){// TODO: Add your control notification handler code hereDWORD 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;GetDlgItemText(IDC_EDIT_SEND,strSend);sendto(m_socket,strSend,strSend,GetLength()+1,0,(SOCKADDR*)&addrTo,sizeof(SOCKADDR));SetDlgItemText(IDC_EDIT_SEND,"");}二、接收数据void CChatDlg::OnRecvData(WPARAM wParam,LPARAM lParam){CString str=(char*)lParam;CString strTemp;GetDlgItemText(IDC_EDIT_RECV,strTemp);str+="\r\n";str+=strTemp;SetDlgItemText(IDC_EDIT_RECV,str);}三、获取IP地址DWORD WINAPI CChatDlg::RecvProc(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(TRUE){retval=recvfrom(sock,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len);if(SOCKET_ERROR==retval)break;sprintf(tempBuf,"%s说:%s",inet_ntoa(addrFrom.sin_addr),recvBuf);::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);}return 0;}四、创建套接字并链接BOOL CChatDlg::lnitsocket(){m_socket=socket(AF_INET,SOCK_DGRAM,0);if(INV ALID_SOCKET==m_socket){MessageBox("套接字创建失败!");return FALSE;}SOCKADDR_IN addrSock;addrSock.sin_family=AF_INET;addrSock.sin_port=htons(6000);addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);int retval;retval=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));if(SOCKET_ERROR==retval){closesocket(m_socket);MessageBox("绑定失败!");return FALSE;}return TRUE;}五、加载套接字BOOL CChatApp::InitInstance(){if (!AfxSocketInit()){AfxMessageBox("加载套接字失败!");return FALSE;}AfxEnableControlContainer();六、方法步骤1、新建工程,file->new->MFC AppWizard(exe),工程名字叫“寒暄”,选择“D基本对话”。

2、删除原来的控件,选择主框,设置属性(标题改为接收数据),放置编辑框(更改ID号IDC_EDIT_RECV,用于显示接收到的数据),在放置一主框(用于发送数据),并在其中放置IP地址控件,放入一编辑框(更改ID号IDC_EDIT_SEND),最后放置发送按钮(更改ID号IDC_BTN_SEND),如图所示:3、加载套接字库寒暄classes ->CMyApp ->lnitlnstance() 输入if (!AfxSocketInit()){AfxMessageBox("加载套接字失败!");return FALSE;}在StdAfx.h 中申请函数,#include <AFxsock.h>4、在CMyDlg中定义成员函数BOOL Initsocket和成员变量SOCKET m_socket 访问权限为私有套接字初始化,编写:BOOL CChatDlg::lnitsocket(){m_socket=socket(AF_INET,SOCK_DGRAM,0);if(INV ALID_SOCKET==m_socket){MessageBox("套接字创建失败!");return FALSE;}SOCKADDR_IN addrSock;addrSock.sin_family=AF_INET;addrSock.sin_port=htons(6000);addrSock.sin_addr.S_un.S_addr=htonl(INADDR_ANY);int retval;retval=bind(m_socket,(SOCKADDR*)&addrSock,sizeof(SOCKADDR));if(SOCKET_ERROR==retval){closesocket(m_socket);MessageBox("绑定失败!");return FALSE;}return TRUE;}5、线程函数在BOOL CMyDlg::OnInitDialog() 中编写程序lnitsocket();RECVPARAM *pRecvParam=new RECVPARAM;pRecvParam->sock=m_socket;pRecvParam->hwnd=m_hWnd;HANDLE hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);CloseHandle(hThread);return TRUE;6、接收数据DWORD WINAPI CChatDlg::RecvProc(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(TRUE) /*循环不断的接收数据*/{retval=recvfrom(sock,recvBuf,200,0,(SOCKADDR*)&addrFrom,&len);if(SOCKET_ERROR==retval)break; /*有错误,终止循环*/sprintf(tempBuf,"%s说:%s",inet_ntoa(addrFrom.sin_addr),recvBuf); /*没有错误,将格式化*/::PostMessage(hwnd,WM_RECVDATA,0,(LPARAM)tempBuf);}return 0;}7、消息的初始化定义消息的值#define WM_RECVDA TA WM_USER+1定义消息响应函数afx_msg void OnRecvData(WPARAM wParam,LPARAM lParam);定义消息映射ON_MESSAGE(WM_RECVDA TA,OnRecvData)消息相应函数的实现void CChatDlg::OnRecvData(WPARAM wParam,LPARAM lParam){CString str=(char*)lParam;CString strTemp;GetDlgItemText(IDC_EDIT_RECV,strTemp);str+="\r\n"; /*换行*/str+=strTemp; /*将新消息显示在第一行,先前的数据在下面*/SetDlgItemText(IDC_EDIT_RECV,str);}8、发送端void CChatDlg::OnBtnSend(){// TODO: Add your control notification handler code hereDWORD dwIP;((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS1))->GetAddress(dwIP); /*获取IP地址*/SOCKADDR_IN addrTo; /*定义地址结构体变量*/addrTo.sin_family=AF_INET;addrTo.sin_port=htons(6000); /*默认端口*/addrTo.sin_addr.S_un.S_addr=htonl(dwIP);CString strSend;GetDlgItemText(IDC_EDIT_SEND,strSend);sendto(m_socket,strSend,strSend,GetLength()+1,0,(SOCKADDR*)&addrTo,sizeof(SOCKADDR)); /*发送数据*/ SetDlgItemText(IDC_EDIT_SEND,""); /*将发送端的文本框设置没空*/}七、遇到的问题1、error C2065: 'INADDY_ANY' : undeclared identifier书写错误,应为INADDR_ANY2、error C2065: ' RecvProc ' : undeclared identifier将ThreadProc改为RecvProc3、error C2664: 'CreateThread' : connot convert parameter 3 form 'unsigned long (void *)' to 'unsigned long(_stdcall*)(void *)'申请为静态函数tatic DWORD WINAPI RecvProc(LPVOID lpParameter);4、error C2065: 'IDC_EDIT_SEND' : undeclared identifier将发送编辑框属性的ID号改为IDC_EDIT_SEND5、在接受文本框,接受的文字并没有换行属性中General Styles 中选择Multiline 使文本框支持多行显示6、如何设置默认用回车键发送文字按钮属性中选择,U默认按钮7、error C2065: 'GetLength' : undeclared identifiersendto(m_socket,strSend,strSend.GetLength()+1,0,(SOCKADDR*)&addrTo,sizeof(SOCKADDR));对函数的调用,符号书写错误8、绑定失败默认端口号被占用,只需更改端口号9.只能给自己聊天(IP地址为:127.0.0.1)孙鑫Vc++课程16课线程间通信用socket或异步套接字。