学习笔记之网络软件设计(二)

来源:互联网 发布:淘宝客上货软件 编辑:程序博客网 时间:2024/05/01 01:07

任务二 简单的聊天程序

一、要求

1.编写两对简单的一对一聊天程序,分别为面向连接方式和无连接方式(我选用无连接方式)
2.当开始通信后,一方先从键盘获得用户字符串,发送到另一方,然后等待对方数据,显示,再循环这个过程
3.而另一方则是先等待对方字符串,显示;然后从键盘获得用户字符串,发送,再循环这个过程。

进阶要求

双方可以自由聊天,即随时都可以输入或显示对方的数据
软件具有图形化界面

二、与任务相关的实验

05-套接字接口函数
07-隐式绑定
11-多路复用
12-阻塞与非阻塞
13-并发服务

三、完成过程

1、服务器端

这个任务我采用的无连接的方式完成。
通信的基本步骤:
1.服务器开启,申请套接字,确定本地端点,默认4660。
2.开启的时候,额外开启一个线程,用于接收来自客户端的消息,并显示在聊天记录中。
3.点击发送按钮,可以将发送消息框中的消息发送出去,并显示在聊天记录中。

以下为部分代码(东拼乱凑的感觉,希望大神指导~~
//定义的部分变量SOCKET s;sockaddr_in local;sockaddr_in remote;int len;CString sendbuf;char recvbuf[128];WSAData wsa;CString buffer;//存放一次的消息static CString save;//存放聊天记录

//点击启动按钮后的执行代码void CTanc_mfc_chat_serverDlg::OnRunbutton() {WSAStartup(0x101,&wsa);s = socket(AF_INET,SOCK_DGRAM,0);//申请套接字local.sin_family = AF_INET;local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//0.0.0.0local.sin_port = htons(0x1234);//port 4660bind(s,(sockaddr*)&local,sizeof(local));//创建服务线程CreateThread(NULL, 0 ,ThreadServer, NULL, 0, NULL);AfxMessageBox("服务器已启动");}

//线程部分的代码,用于接收消息 并显示在聊天记录中DWORD WINAPI ThreadServer(LPVOID lpParameter){while(TRUE){len = sizeof(remote);recvfrom(s,recvbuf,sizeof(recvbuf),0,(sockaddr*)&remote,&len);buffer.Format(_T("客户说 :%s\r\n"),recvbuf);save = save + buffer;buffer.Empty();buffer.FreeExtra();theApp.m_pMainWnd->GetDlgItem(IDC_MESSAGE)->SetWindowText(save);}closesocket(s);//关闭套接字WSACleanup();}

//点击发送按钮执行的代码。将消息发送出去,并显示在聊天记录中void CTanc_mfc_chat_serverDlg::OnSendbutton() {//显示在聊天记录中UpdateData(TRUE);buffer.Format(_T("我说 :%s\r\n"),m_sendMessage);save = save + buffer;buffer.Empty();buffer.FreeExtra();m_message = save;UpdateData(FALSE);//发送消息sendbuf = m_sendMessage;len = sizeof(remote);sendto(s,sendbuf,strlen(sendbuf),0,(sockaddr*)&remote,len);}
效果图:



二、客户端

客户端需要输入服务器IP地址和端口号,然后输入消息,进行发送。

//点击发送执行的代码void CTanc_mfc_chat_clientDlg::OnSend() {//获取IP、端口号和发送的消息UpdateData(TRUE);BYTE nf1, nf2, nf3, nf4;m_serverIPAddress.GetAddress(nf1, nf2, nf3, nf4);sendbuf = m_sendMessage;int port = m_port;buffer.Format(_T("我说 :%s\r\n"),m_sendMessage);save = save + buffer;buffer.Empty();buffer.FreeExtra();WSAStartup(0x101,&wsa);s = socket(AF_INET,SOCK_DGRAM,0);local.sin_family = AF_INET;local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);local.sin_port = htons(0x3412);bind(s,(sockaddr*)&local,sizeof(local));//确定IP和端口号remote.sin_family = AF_INET;remote.sin_addr.S_un.S_un_b.s_b1 = nf1;remote.sin_addr.S_un.S_un_b.s_b2 = nf2;remote.sin_addr.S_un.S_un_b.s_b3 = nf3;remote.sin_addr.S_un.S_un_b.s_b4 = nf4;remote.sin_port = htons(port);len = sizeof(remote);sendto(s,sendbuf,strlen(sendbuf),0,(sockaddr*)&remote,len);m_message = save;UpdateData(FALSE);//创建服务线程CreateThread(NULL, 0 ,ThreadClient, NULL, 0, NULL);}

//用于显示接收消息的线程DWORD WINAPI ThreadClient(LPVOID lpParameter){while(TRUE){len = sizeof(remote);recvfrom(s,recvbuf,sizeof(recvbuf),0,(sockaddr*)&remote,&len);buffer.Format(_T("服务器说 :%s\r\n"),recvbuf);save = save + buffer;buffer.Empty();buffer.FreeExtra();theApp.m_pMainWnd->GetDlgItem(IDC_MESSAGE)->SetWindowText(save);}closesocket(s);WSACleanup();}

效果图:



四、遇见的一些问题

1、CString类的buffer存放一次消息时,前次消息长于后次,前次多余的部分也会显示。如图:

//解决方法buffer.Empty();buffer.FreeExtra();buffer = ""; //这种不行。

2、获取和写入界面数据的方法。
/*用到了两种方法:一个是获取ID的方法二个是UpdateData()方法*/theApp.m_pMainWnd->GetDlgItem(IDC_MESSAGE)->SetWindowText(save);UpdateData(TRUE);UpdateData(FALSE);//我表示没怎么区别搞懂,求具体的文档之类的~~~~

3、待续~~~

五、小结

基本完成了任务的要求,用线程实现了自由聊天,即随时都可以输入或显示对方的数据。对于C++还是不够了解,代码感觉好乱。







0 0
原创粉丝点击