收藏 分销(赏)

网络编程技术课程设计报告样本.doc

上传人:二*** 文档编号:4534203 上传时间:2024-09-27 格式:DOC 页数:34 大小:924.50KB 下载积分:5 金币
下载 相关 举报
网络编程技术课程设计报告样本.doc_第1页
第1页 / 共34页
本文档共34页,全文阅读请下载到手机保存,查看更方便
资源描述
课程设计(论文) 题 目 名 称 聊天软件开发 课 程 名 称 网络编程技术课程设计 学 生 姓 名 学 号 系 、专 业 指 导 教 师 5月 22日 摘 要 聊天程序普通采用互连网中继聊天合同,即双方即时通信过程中必要通过第三方中转,第三方为服务器,聊天程序普通采用UDP合同,在基于UDP合同基本上,聊天过程中消息发送必要遵守某一种商定,这种商定规定了“进入聊室”、“发送聊天信息”和“离开聊天室”数据传播格式,中转者(服务器)通过接受客户端不同数据格式来进行判断消息发送者欲进行操作,然后对消息进行解决后再进行转发。本次课程设计重要是运用MFC所提供各种控件,基于C/S模式,设计一种简朴聊天软件。 核心词:Visual C++6.0,客户端-服务器(C/S)构造,简朴聊天软件 目 录 1 前言 1 2 需求分析 1 2.1 任务和规定 1 2.2 应实现功能 2 2.3 界面及控件变量 2 3 分析和设计 4 3.1 系统分析及设计思路 4 3.2 重要控件功能 5 3.3 程序流程图 6 (一)流程运营框架 6 (二)服务端 7 (三)客户端 9 4 详细代码实现 12 4.1 服务器 12 4.2客户端 18 5 课程设计总结 24 5.1 程序运营成果或预期运营成果 24 5.2 设计结论 25 参照文献 27 致 谢 27 1 前言 本次课程设计重要是运用MFC所提供各种控件,基于C/S模式,设计一种简朴聊天软件。聊天软件由客户端和服务器两某些构成,服务器充当“中转者”职能,客户端将自己消息一方面发给服务器,服务器再依照需要将它们转发给其她客户端。聊天程序普通采用互连网中继聊天合同,即双方即时通信过程中必要通过第三方中转,第三方为服务器,聊天程序普通采用UDP合同,在基于UDP合同基本上,聊天过程中消息发送必要遵守某一种商定,这种商定规定了”进入聊天室”,”发送聊天信息”和”离开聊天室”数据传播格式,中转者(服务器)通过接受客户端不同数据格式来进行判断消息发送者欲进行操作,然后对消息进行解决后再进行转发,服务器依照接受到不同消息格式做出不同解决。 2 需求分析 2.1 任务和规定 本次课程设计内容任务是简朴群聊软件设计与实现。三人以上为一组,其中一种同窗为群聊软件服务器端,此外同窗为群聊软件客户端,服务器启动后发布其IP地址和端标语,客户端用服务器IP地址和端标语进行登录,观测服务器与客户端显示成果,然后由客户端发送群聊消息,观测服务器与各客户端显示成果。 详细规定如下: 1.采用客户端——服务器(C/S)构造,聊天室软件由客户端和服务器两某些构成,即创立两个工程,服务器(SelfRoom)和客户端(SelfChat)。 2.服务器对话框界面应具备聊天室IP、端口、启动、关闭、聊天室动态、在线顾客等基本内容,而客户端对话框界面应具备昵称、聊天室IP、端口、登录、离开、聊天记录、在线朋友等基本内容,添加相应成员函数,使程序能正常运营。 3.聊天程序采用UDP合同,基于UDP合同聊天过程中遵守一种商定,这种商定规定了“进入或离开聊天室”和“发送聊天信息”数据传播格式,服务器作为“中转者”通过接受客户端不同数据格式来进行判断消息发送者欲进行操作,然后对消息进行解决后再进行转发。 2.2 应实现功能 本次课程设计内容是群聊软件设计与实现,采用MFC类编程。下面简介一下服务器和客户端所实现功能。 服务器界面中有管理员、聊天室IP、端口、聊天室动态和在线顾客列表,尚有“启动”、“关闭”、“退出”按钮。运营服务器时,先进行管理员、聊天室IP、端口配备,点击“启动”按钮后,聊天室动态文本框里会显现“聊天室启动成功”等消息以及当时得时间,便可等待成员加入;当有成员加入时,也会有相应提示信息,顾客列表也会及时更新;当客户端发来消息,服务器会将此消息转发给每一种成员;当列表中所有成员都离开时,服务器可点击“关闭”,即关闭聊天室。 客户端界面有您昵称、聊天室IP、端口、聊天文本框、在线朋友列表,尚有“进入”、“离开”、“发送”按钮。运营客户端时,先进行昵称、聊天室IP、端口配备,点击“进入”按钮,与服务器进行了连接;连接成功后,可发送聊天消息点击“发送”就能将消息发送到服务器,让服务器进行解决,发送信息会显示在聊天框里,每条消息前面还附有发送消息时时间,在线朋友列表中会显示已进入聊天室成员,可以与她们进行群聊,由于这只是简朴群聊软件,因此只能发送文字信息,不具备发送表情、文献等高档功能;当有成员加入或离开聊天室时,聊天框内会有提示信息,在线朋友列表也会即时更新;当客户端想离开时,可以点击“离开”按钮,即可退出聊天室。 2.3 界面及控件变量 (一)服务器 运营界面,如图2.1。 图2.1 服务器界面图 (二)客户端 运营界面,如图2.2。 图2.2客户端运营界面图 3 分析和设计 3.1 系统分析及设计思路 本次聊天软件采用MFC编程,需要创立2个工程,分别是客户端工程SelfChat和服务器工程SelfRoom,由于本次软件需用到套接字类,因此在创立工程时候需要选取“Windows Sockets”复选框,并都基于基本对话框。在制作服务器时候需要添加两个基于CSocket套接字:CClientSocket(用来监听)和CServerSocket(为每个加入聊天室客户端生成一种相应对象与之通信),此外添加一种C++构造体tagHeader(用于客户端和服务器之间辨识消息类型)。在制作客户端时添加一种基于CSocket套接字类CClientSocket(用于连接服务器通信),和服务器同样要添加一种C++构造体tagHeader。 整个流程中事件时序如下: 1. 服务器配备管理员、聊天室IP以及端口后,单击“启动”按钮,此时服务器积极调用Listen()开始监听。 2. 客户端配备昵称、聊天室IP以及端口后,单击“进入”按钮,此时客户端向服务器发起连接Connect()祈求,若祈求被接受,则紧接着发送会话消息。 3. 服务器CServerSocket类接受祈求并触发OnAccept()事件,该事件过程创立相应祈求方客户端CClientSocket类对象并添加到Socket队列。 4. 更多成员客户端加入时,服务器重复环节3。 5. 某个成员(客户端)要发送聊天消息时,在发送信息文本框中编辑文字,单击“发送”按钮向服务器发出消息。 6. 某个成员(客户端)发来消息到达服务器,触发服务器Socket队列中相应当客户端CClientSocket类对象OnReceive()事件,对发来消息进行解决。 7. 服务器上相应当客户端CClientSocket类对象,依照消息头tagHeader构造中type字段辨别消息类型:若type=LOGIN_IO,则表达有新成员加入,用广播方式告知所有其她成员客户端,并调用服务器UpdateUser()更新服务器顾客列表;若type=SEND_MESSAGE,则表达这只是普通成员发言信息,直接广播转发该消息就可以了。 8. 服务器发出消息到达客户端,触发客户端本地OnReceive()事件,客户端本地Socket依照消息头tagHeader构造中type字段辨识消息类型:若type=LOGIN_IO,则表达有新成员加入或已有聊天成员下线退出,于是调用客户端UpdateUser()函数更新本地顾客列表;若type=SEND_MESSAGE,则表达这是聊天室中其她成员发来消息,调用GetMsgFromRoom()函数接受之后显示在客户端屏幕上。 9. 某个成员要下线时,单击“离开”按钮,关闭本地Socket。 10. 一旦某成员退出,关闭了自己客户端程序本地Socket,就会触发其在服务器上Socket队列中相应CClientSocket类对象Onclose()事件,由CClientSocket类对象发消息告知其她成员有人退出,并调用UpdateUser()更新服务器顾客列表。 11. 当最后一种成员离开聊天室后,管理员可单击“关闭”按钮关闭服务器。 3.2 重要控件功能 服务器重要控件功能见表3.1,客户端重要控件功能见表3.2。 控件 功能 “管理员”文本框 配备管理员名称 IP控件 配备聊天室IP “端口”文本框 配备聊天室端口 “聊天室动态”只读文本框 显示聊天室动态,涉及聊天室启动、关闭提示信息,成员登录、离开提示信息以及聊天消息 “顾客在线”列表框 显示已进入聊天室成员 “启动”按钮 启动聊天室 “关闭”按钮 关闭聊天室 “退出”按钮 退出 表3.1服务器重要控件功能 控件 功能 “您昵称”文本框 配备昵称 IP控件 配备聊天室IP “端口”文本框 配备聊天室端口 “在线朋友”列表框 显示已进入聊天室成员 “聊天”只读文本框 显示聊天室动态,涉及聊天室启动、关闭提示信息,成员登录、离开提示信息以及聊天消息 “发送”信息文本框 编辑要发送消息 “发送”按钮 将消息发送出去 “进入”按钮 进入聊天室 “离开”按钮 离开聊天室 “退出”按钮 退出 表3.2客户端重要控件功能 3.3 程序流程图 (一)流程运营框架 图3.1 流程运营框架程序流程图 (二)服务端 1.服务器“启动”按钮程序流程图 如图3.2 图3.2 服务器“启动”按钮程序流程图 2.客户端发送消息到达服务器后,触发服务器Socket队列相应当客户端给套接字OnReceive()事件 如图3.3 图3.3 服务器OnReceive()事件程序流程图 3.服务器UpdateUser函数过程流程图 如图3.4 图3.4 服务器UpdateUser函数程序流程图 4.服务器OnClose()事件流程图 如图3.5 图3.5 服务器OnClose()事件流程图 (三)客户端 1.客户端“进入”按钮事件流程图 如图3.6 图3.6 客户端“进入”按钮事件程序流程图 2.客户端“发送”按钮事件流程图 如图3.7 图3.7 客户端“发送”按钮流程流程图 3.客户端本地OnReceive()事件流程图 如图3.8 图3.8 客户端本地OnReceive()事件流程图 4.客户端GetMsgFromRoom()和UpdateUser()函数流程图 如图3.9 图3.9 客户端GetMsgFromRoom()和UpdateUser()函数程序流程图 5.客户端“离开”函数流程图 如图3.10. 图3.10 客户端“离开”函数流程图 4 详细代码实现 4.1 服务器 1.单击“启动”按钮,添加函数: void CSelfRoomDlg::OnButton1() { // TODO:Add your control notification handler code here UpdateData(); //刷新界面,获得顾客输入 m_pSocket=new CServerSocket; BYTE nFild[4]; CString sIP; ServerIP.GetAddress(nFild[0],nFild[1],nFild[2],nFild[3]); //获取管理员配备IP sIP.Format("%d.%d.%d.%d",nFild[0],nFild[1],nFild[2],nFild[3]); CTime time=CTime::GetCurrentTime(); //获取当前时间 //下面开始输入完整性验证 if(m_strName.IsEmpty()) { AfxMessageBox("请先登记管理员名!"); return; } if(sIP.IsEmpty()) { AfxMessageBox("请配备聊天室IP!"); return; } if(sPort.IsEmpty()) { AfxMessageBox("请配备要开放窗口!"); return; } //界面 m_Admin.EnableWindow(false); ServerIP.EnableWindow(false); ServerPort.EnableWindow(false); m_Start.EnableWindow(false); m_Stop.EnableWindow(true); m_Exit.EnableWindow(false); //启动聊天室,一方面创立用于监听套接字 if(m_pSocket->Create(atoi(sPort),1,sIP)) { m_MessageList.SetWindowTextA(""); m_MessageList.ReplaceSel("聊天室启动成功!\r\n"); CString t=time.Format("%Y-%m-%d"); m_MessageList.ReplaceSel("日期:"+t+"\r\n"); t=time.Format("%H:%M:%S"); //获得聊天室启动时刻信息 theApp.m_strName=m_strName; //记录管理员名 m_MessageList.ReplaceSel(t+"管理员"+theApp.m_strName+"开放聊天室\r\n"); } if(m_pSocket->Listen()) //监听开始 { m_MessageList.ReplaceSel("等待成员加入…\r\n"); } //当前暂时还无人加入聊天,因而在线顾客列表中仅管理员一人 m_UserList.ResetContent(); m_UserList.AddString(theApp.m_strName+"(管理员)"); this->SetWindowTextA("管理员:"+m_strName+"-SelfRoom"); } 2.客户端顾客发送消息到达服务器OnReceive()事件: void CClientSocket::OnReceive(int nErrorCode) { // TODO:Add your specialized code here and/or call the base class char buff1[sizeof(Header)]; memset(buff1,0,sizeof(buff1)); Receive(buff1,sizeof(buff1));//一方面接受信息头部 this->AsyncSelect(FD_CLOSE|FD_READ|FD_WRITE); Header*header=(Header*)buff1; int length=header->len; char type=header->type;//解析头部内容 if(type==LOGIN_IO) //头部类型为LOGIN_IO,表达是新成员加入 { char buff[1000]; memset(buff,0,sizeof(buff)); Receive(buff,length);//继续接受这条信息数据某些(新成员名) this->AsyncSelect(FD_CLOSE|FD_READ|FD_WRITE); m_dlgServer->UpdateData(); CTime time=CTime::GetCurrentTime(); CString t=time.Format("%H:%M:%S"); CEdit*p_Edit=(CEdit *)::AfxGetMainWnd()->GetDlgItem(IDC_EDIT_INFO); //生成告知信息 CString strTemp=t+" "+CString(buff)+"进入聊天室/\r\n"; p_Edit->ReplaceSel(strTemp); m_strName=buff;//将新成员顾客名登记在服务器相应Socket中 Header head; head.type=SEND_MESSAGE; head.len=strTemp.GetLength(); Header head_history; head_history.type=SEND_MESSAGE; //生成"欢迎"信息 m_dlgServer->m_history+=m_strName+"欢迎您加入!"; head_history.len=m_dlgServer->m_history.GetLength(); CClientSocket *curr=NULL; POSITION pos=clist->GetHeadPosition(); while(pos!=NULL) { curr=(CClientSocket *)clist->GetNext(pos); if(curr->m_strName==m_strName)//为新加入那个成员发送欢迎信息 { curr->Send((char*)&head_history,sizeof(Header)); curr->Send(m_dlgServer->m_history,m_dlgServer->m_history.GetLength()); } else//向聊天室中其她老成员发送告知信息,告知有新成员加入 { curr->Send((char*)&head,sizeof(Header)); curr->Send(strTemp,strTemp.GetLength()); } } m_dlgServer->UpdateUser(this);//更新顾客列表 } if(type==SEND_MESSAGE)//头部类型为SEND_MESSAGE,表达是成员之间聊天信息 { char buff[1000]; memset(buff,0,sizeof(buff)); Receive(buff,sizeof(buff)); this->AsyncSelect(FD_CLOSE|FD_READ|FD_WRITE) ; CTime time=CTime::GetCurrentTime(); CString t=time.Format("%H:%M:%S"); CString nikeName=this->m_strName; CString strTemp=t+" "+nikeName+"说:"+CString(buff)+"\r\n"; CString str=nikeName+" "+t+"\r\n"+" "+CString(buff); CEdit*p_Edit=(CEdit*)::AfxGetMainWnd()->GetDlgItem(IDC_EDIT_INFO); p_Edit->ReplaceSel(strTemp); CClientSocket*curr=NULL; POSITION pos=clist->GetHeadPosition(); while(pos!=NULL)//向聊天室内所有成员转发聊天信息内容 { curr=(CClientSocket*)clist->GetNext(pos); curr->Send((char*)header,sizeof(Header)); curr->Send(str,str.GetLength()); } } CSocket::OnReceive(nErrorCode); CSocket::OnReceive(nErrorCode); } 3.服务器检测到新成员加入,调用UpdateUser()函数更新顾客列表: void CSelfRoomDlg::UpdateUser(CClientSocket *pSocket) { m_UserList.ResetContent(); m_UserList.AddString(theApp.m_strName+"管理员"); CString user_info; user_info=theApp.m_strName+"(管理员)"+"&"; if(pSocket!=NULL) { CClientSocket *pSock=NULL; POSITION pos=pSocket->clist->GetHeadPosition(); while(pos!=NULL) { pSock=(CClientSocket *)pSocket->clist->GetNext(pos); m_UserList.AddString(pSock->m_strName); user_info+=(pSock->m_strName+"&"); } Header head; head.type=LOGIN_IO; head.len=user_info.GetLength(); POSITION po=pSocket->clist->GetHeadPosition(); while(po!=NULL) { pSock=(CClientSocket *)pSocket->clist->GetNext(po); pSock->Send((char *)&head,sizeof(Header)); pSock->Send((LPCTSTR)user_info,user_info.GetLength()); } } } 4.成员退出,关闭自己Socket,触发服务器OnClose()事件: void CClientSocket::OnClose(int nErrorCode) { // TODO:Add your specialized code here and/or call the base class POSITION pos=clist->Find(this); if(pos!=NULL){ clist->RemoveAt(pos); //移除服务器Socket队列中套接字 CTime time=CTime::GetCurrentTime(); CString t=time.Format("%H:%M:%S"); CEdit*p_Edit=(CEdit*)m_dlgServer->GetDlgItem(IDC_EDIT_INFO); CString strTemp=t+" "+this->m_strName+"离开聊天室\r\n"; p_Edit->ReplaceSel(strTemp); Header head; head.type=SEND_MESSAGE; head.len=strTemp.GetLength(); CClientSocket*curr=NULL; POSITION pos=clist->GetHeadPosition(); while(pos!=NULL) //将此顾客离开消息告知其她成员 { curr=(CClientSocket*)clist->GetNext(pos); curr->Send((char*)&head,sizeof(Header)); curr->Send(strTemp,strTemp.GetLength()); } m_dlgServer->UpdateUser(this); //更新服务器列表 this->Close(); delete this; } CSocket::OnClose(nErrorCode); } 4.2客户端 1.客户端“进入”按钮事件过程代码如下: void CSelfChatDlg::OnButton1() { // TODO:Add your control notification handler code here UpdateData(); m_pSocket=new CClientSocket; m_pSocket->GetDlg(this); //获取主界面指针 BYTE nFild[4]; CString sip; ServerIP.GetAddress(nFild[0],nFild[1],nFild[2],nFild[3]); sip.Format("%d.%d.%d.%d",nFild[0],nFild[1],nFild[2],nFild[3]); //获取顾客输入服务器IP //输入完整性验证 if (m_strName.IsEmpty()) { AfxMessageBox("给自己起个昵称吧!"); return; } if(sip.IsEmpty()) { AfxMessageBox("请指定IP地址!"); return; } if(strport.IsEmpty()) { AfxMessageBox("请指定连接端口!"); return; }//发起连接 if(!m_pSocket->Create()) { AfxMessageBox("网络创立错误!!!"); m_pSocket->Close(); return; } if(!m_pSocket->Connect(sip,atoi(strport))) { AfxMessageBox("连接服务器失败!!!"); m_pSocket->Close(); return; } //界面 m_Usr.EnableWindow(false); ServerIP.EnableWindow(false); m_port.EnableWindow(false); m_Enter.EnableWindow(false); m_Quit.EnableWindow(true); m_EditWords.EnableWindow(true); m_EditWords.SetFocus(); m_Send.EnableWindow(true); m_Exit.EnableWindow(false); Header head; head.type=LOGIN_IO; head.len=m_strName.GetLength(); m_pSocket->Send((char*)&head,sizeof(Header)); m_pSocket->Send(m_strName,m_strName.GetLength()); //发送会话消息 theApp.m_strName=m_strName; m_MessageList.SetWindowTextA(""); this->SetWindowTextA(m_strName+"-SelfChat");//标题栏实时动态显示顾客名 } 2.“发送”按钮事件解决代码如下: void CSelfChatDlg::OnButton3() { // TODO:Add your control notification handler code here UpdateData(); if(m_strMessage=="") { AfxMessageBox("不能发送空消息"); m_EditWords.SetFocus(); return; } Header head; head.type=SEND_MESSAGE; //聊天内容,消息头类型为SEND_MESSAGE head.len=m_strMessage.GetLength(); m_pSocket->Send((char*)&head,sizeof(Header)); if(m_pSocket->Send(m_strMessage,m_strMessage.GetLength())) { m_strMessage=""; UpdateData(FALSE); m_EditWords.SetFocus(); return; } else { AfxMessageBox("网络传播错误!"); } } 3.客户端本地OnReceive()事件过程: void CClientSocket::OnReceive(int nErrorCode) { // TODO:Add your specialized code here and/or call the base class char buff[sizeof(Header)]; memset(buff,0,sizeof(buff)); Receive(buff,sizeof(buff)); this->AsyncSelect(FD_CLOSE|FD_READ|FD_WRITE); Header *header=(Header*)buff; int length=header->len; char type=header->type; if(type==SEND_MESSAGE) { chatDlg->GetMsgFromRoom(); } if(type==LOGIN_IO) { chatDlg->UpdateUser(); } CSocket::OnReceive(nErrorCode); CSocket::OnReceive(nErrorCode); } 4.对于接受两类不同消息分别调用两个解决GetMsgFromRoom()和UpdateUser()函数,代码如下: BOOL CSelfChatDlg::GetMsgFromRoom() { char buff[1000]; memset(buff,0,sizeof(buff)); m_pSocket->Receive(buff,sizeof(buff));//接受信息 m_pSocket->AsyncSelect(FD_CLOSE|FD_READ|FD_WRITE); CString strTemp=buff; strTemp+="\r\n"; m_MessageList.ReplaceSel(strTemp);//直接显示在界面上即可 return TRUE; } void CSelfChatDlg::UpdateUser() { char buff[1000]; memset(buff,0,sizeof(buff)); m_pSocket->Receive(buff,sizeof(buff));//接受到最新在线顾客名单 m_pSocket->AsyncSelect(FD_CLOSE|FD_READ|FD_WRITE); CString user_info=buff; CString array[100]; int b=0; for(int i=0;i<user_info.GetLength();i++) { if(i!=(user_info.GetLength()-1)) { if(user_info[i]=='&'){ b++; } else { array[b]=array[b]+user_info[i]; } } } m_UserList.ResetContent(); for(int j=0;j<b+1;j++) { m_UserList.AddString(array[j]);//顾客名依次显示于界面列表中 } } 5.客户端“离开”按钮事件过程代码如下: void CSelfChatDlg::OnButton2() { if(m_pSocket){ m_pSocket->Close(); delete m_pSocket;//离开时记得关闭,销毁Scoket } m_UserList.ResetContent();
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 学术论文 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服