




已阅读5页,还剩28页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
软件项目实训报告书 学院:_计算机科学与技术_ 专业:_ 软件工程_ _ 组长:_ _目录第一章 项目简介1局域网聊天系统1第二章 需求分析1一 任务概述11.1 目标11.2 软件总体功能结构图11.3 系统用例图21.4 顶层数据流图21.5 二层数据流图31.6 用户的特点31.7 假定与约束3二 需求规定42.1对性能的规定42.1.1精度42.1.2 时间特性耍求42.2 输出要求42.3 数据管理能力要求42.4 故障处理要求4三 运行环境规定4设备4四 接口5用户接口5硬件接口5通信接口5第三章 总体设计5概述5一 系统主要功能的工作流程6二 服务器端总体设计7三 客户端总体设计8第四章 详细设计8一 概述8二 服务器端82.1 服务器主模块10三客户端113.1登录模块113.2注册模块113.3 主模块113.4私聊模块11第五章 实现和结果115.1实现115.1.1服务器的实现代码:115.1.2客户端的实现代码255.2 结果38第六章 测试与调试401 测试环境配置402 功能性测试403容错性测试404易用性测试405文档测试41第七章 总结41参考文献41成员信息:课题名称小组成员专业计算机科学与技术学院软件工程系姓名学号班级任务客户端注册登录聊天0902客户端离线信息及程序美化0902服务器端信息收发及测试调试0902服务器端数据库29第一章 项目简介局域网聊天系统 随着互联网的发展应用比较广泛,学校、机房、宿舍等地方都是应用局域网的地方,本项目要求所设计实现的局域网聊天系统能够实现局域网的聊天、聊天内容的保存和文件的传递等功能,并使用TCP/UDP作为该系统的通讯协议。第2章 需求分析一 任务概述1.1 目标 随着办公室工作量日益增加,大家交流日益密切,但由于聊天工具的不足,导致了大家的交流上的一些不便,故我们小组就根据这个背景开发此软件,它主要特点较高通用性即在任意局域网内可以运行,系统具有较高的可移植性和使用性、也包含实用性各及时性,但系统双方的交流可以在短期内进行,以达到最快速度,不但能进行普通文字通信,而且也增加了文件传输功能,如果在后期进度正常进行的情况下会进一步增加语音实时通信以及视频实时通信模块。1.2 软件总体功能结构图局域网聊天系统服务器端客户端注册模块用户资料更改查看好友资料登陆模块聊天模块在线用户模块处理信息更新用户列表1.3 系统用例图1.4 顶层数据流图客户端1服务器客户端2数据库1.5 二层数据流图客户端登陆窗口主面板聊天处理传文件增加,查找,好友查看信息客户端N服务器登陆认证1.6 用户的特点用户能够熟练使用计算机,熟悉相关WINDOWS。 1.7 假定与约束假定项目组成员不无故缺席且认真工作,本软件能在6月29日之前完成。二 需求规定2.1对性能的规定 2.1.1精度 按相关提示输入。2.1.2 时间特性耍求响应时间:所有的发送操作响应时间一般不超过1秒,大量的信息发送,呈现应该在5秒内显示或者提示相关出错信息。更新处理时间:所有提交数据一般在3秒内相应。2.2 输出要求文字数字等相关信息。2.3 数据管理能力要求聊天记录近万条,在需要时能及时存取。相关配置信息,需要时能即使读取。2.4 故障处理要求聊天记录及配置文件必须按日、按周进行及时的备份。三 运行环境规定 设备P3处理器以上,内存:256M以上硬盘:50M空余空间四 接口用户接口用户界面:采用Windows的通用图形界面,对用户友好,且必须对鼠标键盘提供支持,界面设计应遵循:1.尽量保持一致性:界面规范应遵循Winows软件界面的规范2.设计完整的对话过程:系统的每d一次对话都应该有明确的次序:开始、中间处理过程、结束。3.提供简单的错误处理机制4.提供信息反馈:用多种信息提示用户当前软件运行状态,软件界面元件的功能。5.操作可逆:其动作可以是单个的操作,或者是一个相对独立的操作序列。6.设计良好的联机帮助7.显示启动画面:画面简洁明快,富有现代气息。硬件接口支持一般的PC机,笔记本电脑通信接口 本产品用户各终端和服务器属于一个局域网,网内采用TCP/IP或UDP协议。第3章 总体设计概述 本软件系统设计分为服务器端应用程序和客户端应用程序两大部分,采用套接字进行网络编程。为了传输数据采用了udp的连接方式。一 系统主要功能的工作流程 客户端与服务器的实时通信是本系统局域网络通信软件的主要功能之一,其工作流程主要如下:. 服务器端启动程序,启动监听端口(默认监听端口为9999)进入监听状态,等待客户端的连接请求。 客户端发送连接请求和相应的用户信息。 服务器端接受用户连接请求,进行用户信息验证和相应的请求处理操作,并将处理结果反馈给客户端。如果验证成功,则将在线用户列表信息发送给客户端,并通知客户端启动聊天接收线程。 客户端接收服务器端发送过来的好友信息,建立socket与其他在线用户进行实时通信。流程图如下:二 服务器端总体设计服务器端主要功能:(1) 用户信息存储管理:主要用来验证、存储、向客户端发送用户信息,如用户账号,用户密码。(2) 用户请求处理:主要用来处理客户端的各种请求信息,包括连接请求和注册请求。服务器端程序的基本工作流程如下:(1) 打开预设定的网络端口,监听客户端的信息请求;(2) 对登陆的请求,进行用户账号与密码的验证,并作出相应的处理。如果验证成功,则向客户端返回其他用户在线离线信息,否则提示用户登陆不成功。(3) 对于客户端提出的用户账号申请请求,则核对用户提交的信息,并进行保存,然后把申请成功的账号发送给用户。三 客户端总体设计客户端主要功能包括:(1) 网络设置功能模块:用来设置实时通信然见客户端索要连接的服务器ip(2) 账号申请模块:应用于第一次使用本软件的用户申请账号。如果申请成功,则返回客户端一个系统内唯一的账号作为以后用户登陆的身份标识。(3) 连接服务器功能模块:应用于已经获取了账号的用户,登陆到系统中,以便与其他在线用户发送消息。(4) 实时通信功能模块:针对已经登陆的用户与其他在线好友进行公聊与私聊。(5) 离线消息发送与接收:针对离线的人发送离线消息,上线并接受客户端基本工作流程:(1) 局域网内每个成员打开客户端软件后,向系统服务器申请一个用户账号并设置密码。(2) 以该账号密码登陆系统,与其他在线用户发送消息。第4章 详细设计一 概述 总体叙述分为服务器和客户端分别开发。二 服务器端 服务器端始终运行在服务器,始终建立两个socket来监听客户端发来的连接。CServerSocket和CClientSocket,其中CServerSocket用来接收客户端发来的注册,登录,确认等信息,而CClientSocket则是用来处理聊天室等信息的转发。 ( 图2-1)启动登陆等待客户端登陆客户端用户创建子套接字MessageCListenSocketCClientSocketMessage登陆成功连接上发送message显示找到客户端并显示登陆失败发送ID和IP2.1 服务器主模块 用来显示哪个用户已经所有进入或者注册局域网的活动,比如显示某个用户成功注册,或者某个用户成功登陆客户端,以及接受用户注册消息和写入数据操作以及对数据库进行操作增删,CServerSocket负责两个客户端之间私聊的消息的转发以及离线消息的推送。三客户端3.1登录模块填写服务器IP地址,如果有账号直接登录,如有没有则进入注册模块进行 注册。3.2注册模块通过用户填写各种信息,然后通过之前建立的CClientSocket发送到服务器, 再通过服务器保存到服务器本地端的数据库中。3.3 主模块负责显示每一个在线或者离线的用户状态,以及维持一个CEdit用来显示每 一个用户发来的消息,也就是所谓聊天室的功能吧。3.4私聊模块当用户选择某个用户进行私聊获得对方同意之后,开始进行私聊,以及开始进行传送文件活动(目前暂时未实现);第五章 实现和结果5.1实现5.1.1服务器的实现代码:aClientSocket类void CClientSocket:OnReceive(int nErrorCode) /重载函数(在本地套接字接收到消息时自动调用它进行消息处理)/ TODO: Add your specialized code here and/or call the base classchar buff1sizeof(Header);memset(buff1, 0, sizeof(buff1); /初始化为0Receive(buff1,sizeof(buff1); /接收信息Header *header = (Header*)buff1;int length = header-len;char type = header-type;if (type = RECV_LEAVEMESSAGE)char buff1000;memset(buff,0,sizeof(buff);Receive(buff,length); /接收到源主机用户名+&/通过buff 中的 用户名 在数据库中 查找 它需要的数据CString str = m_dlgServer-QueryLeaveMsg(buff);strcat(buff,str);/目的主机 & 源主机 & 消息内容CClientSocket *curr = NULL;POSITION pos = clist-GetHeadPosition();/返回第一个元素的POSITIONwhile (pos != NULL)/向所有在线 用户发送离线消息curr = (CClientSocket *)clist-GetNext(pos);/返回下一个元素的CObject*curr-Send(char *)header,sizeof(Header);/发送命令字 curr-Send(buff, sizeof(buff);if(type = SEND_MESSAGE)char buff1000;memset(buff,0,sizeof(buff); /初始化为0Receive(buff,sizeof(buff); /接收信息/遍历用户套接字链表将用户发送来的消息发送给在线列表的每一个用户CClientSocket *curr = NULL; /返回第一个元素的POSITIONPOSITION pos = clist-GetHeadPosition(); while (pos != NULL) curr = (CClientSocket *)clist-GetNext(pos); /返回下一个元素的CObject* curr-Send(char *)header,sizeof(Header); curr-Send(buff, sizeof(buff);if(type = LOGIN_IO)char buff1000;memset(buff,0,sizeof(buff);Receive(buff,length); m_strNick=m_dlgServer-SelstrName(buff); /通过账号 得到昵称m_strPass=m_dlgServer-SelstrPass(buff); /通过账号 得到密码if(type = ASK_NUM)/申请账号命令字char buff1000;memset(buff,0,sizeof(buff);/初始化为0Receive(buff,length);CString strNum;CString strNick;/将用户资料插入数据库strNum=m_dlgServer-InsertUserInfo(buff);/将用户信息存到数据库中strNick=m_dlgServer-SelstrName(strNum);/将系统分配给用户的账号返回给用户if(strNum=*)Header head;head.type = ASKNUM_FAILED;head.len = strNum.GetLength();this-Send(char *)&head,sizeof(Header);this-Send(strNum,strNum.GetLength();elseHeader head;head.type = ASK_NUM;head.len = strNum.GetLength();this-Send(char *)&head,sizeof(Header);this-Send(strNum,strNum.GetLength();CTime time = CTime:GetCurrentTime();CString t = time.Format(%Y-%m-%d %H:%M:%S);CEdit *p_Edit = (CEdit *):AfxGetMainWnd()-GetDlgItem(IDC_EDIT_INFO);CString strTemp =t + : + strNick/*CString(buff)*/ + 申请了一个帐号:+strNum+rn;p_Edit-ReplaceSel(strTemp);m_strName = strNick/*buff*/;if(type = PASS_SUCCESS) char buff1000;memset(buff,0,sizeof(buff);Receive(buff,length);/接收用户登陆时输入的密码CString strPass=buff;if (m_dlgServer-m_UserList.FindString(-1,m_strNick) != LB_ERR) /列表中已经存在Header head;head.type = PASS_FAILED;head.len = m_strName.GetLength();this-Send(char *)&head,sizeof(Header);this-Send(m_strName,m_strName.GetLength();else if(strPass=m_strPass) /判断密码是否正确/-发送密码正确信息-Header head;head.type = PASS_SUCCESS;head.len = m_strNick.GetLength();this-Send(char *)&head,sizeof(Header);this-Send(m_strNick,m_strNick.GetLength(); /-在服务器监视编辑框内显示用户进入聊天室-CTime time = CTime:GetCurrentTime();CString t = time.Format(%Y-%m-%d %H:%M:%S);CEdit *p_Edit = (CEdit *):AfxGetMainWnd()-GetDlgItem(IDC_EDIT_INFO);CString strTemp =t + : + m_strNick + 进入聊天室+rn;p_Edit-ReplaceSel(strTemp);m_strName = m_strNick;m_dlgServer-UpdateUser(this,m_strName,1);/更新在线用户列表(服务器和客户端都更新)/检测是否有离线消息else /发送密码错误信息Header head;head.type = PASS_FAILED;head.len = m_strName.GetLength();this-Send(char *)&head,sizeof(Header);this-Send(m_strName,m_strName.GetLength();if (type = LEAVE_MESSAGE)char buff1000;memset(buff,0,sizeof(buff); /初始化为0Receive(buff,sizeof(buff); /接收信息m_dlgServer-InsertLeaveMsg(buff);if(type = PRIVATE_ASK) /单独聊天命令字char buff1000;memset(buff,0,sizeof(buff);Receive(buff,sizeof(buff);CClientSocket *curr = NULL;POSITION pos = clist-GetHeadPosition(); /返回第一个元素的POSITIONwhile (pos != NULL)curr = (CClientSocket *)clist-GetNext(pos); /返回下一个元素的CObject*curr-Send(char *)header,sizeof(Header); curr-Send(buff, sizeof(buff);if(type = PRIVATE_REFUSE)char buff1000;memset(buff,0,sizeof(buff);Receive(buff,sizeof(buff);CClientSocket *curr = NULL;POSITION pos = clist-GetHeadPosition(); /返回第一个元素的POSITIONwhile (pos != NULL)curr = (CClientSocket *)clist-GetNext(pos); /返回下一个元素的CObject*curr-Send(char *)header,sizeof(Header); curr-Send(buff, sizeof(buff);if(type = PRIVATE_MESSAGE)char buff1000;memset(buff,0,sizeof(buff);/初始化为0Receive(buff,sizeof(buff); /接收信息CClientSocket *curr = NULL;POSITION pos = clist-GetHeadPosition();/返回第一个元素的POSITIONwhile (pos != NULL)curr = (CClientSocket *)clist-GetNext(pos);/返回下一个元素的CObject*curr-Send(char *)header,sizeof(Header); curr-Send(buff, sizeof(buff);CSocket:OnReceive(nErrorCode);void CClientSocket:OnClose(int nErrorCode)/重载的OnClose函数,在有套接字断开连接时会自动调用/ TODO: Add your specialized code here and/or call the base classPOSITION pos = clist-Find(this);if(pos != NULL)clist-RemoveAt(pos);/ 删除链表中退出的用户套接字CTime time = CTime:GetCurrentTime(); /获取当前系统时间CString t = time.Format(%Y-%m-%d %H:%M:%S);CEdit *p_Edit = (CEdit *)m_dlgServer-GetDlgItem(IDC_EDIT_INFO);CString strTemp = t + : + this-m_strName + 离开聊天室+rn;p_Edit-ReplaceSel(strTemp);/在IDC_EDIT_INFO中输出字符串m_dlgServer-UpdateUser(this,this-m_strName,2);this-Close();delete this;CSocket:OnClose(nErrorCode);void CClientSocket:ServerClose()CString buff;buff=m_strNick;Header head;head.type = SERVER_STOP;head.len = buff.GetLength();CClientSocket *curr = NULL;POSITION pos = clist-GetHeadPosition(); /返回第一个元素的POSITIONwhile (pos != NULL)curr = (CClientSocket *)clist-GetNext(pos); /返回下一个元素的CObject*curr-Send(char *)&head,sizeof(Header); curr-Send(buff, sizeof(buff); c . ChatServerDlg类void CChatServerDlg:UpdateUser(CClientSocket *pSocket,CString m_usrLeaveName,int type)/type=1 userlogin type=2 userleaveCString user_info=;CString str=;CClientSocket *pSock = NULL;if (type=2)m_ListClose.AddString(m_usrLeaveName);if (LB_ERR!=m_ListClose.FindString(-1,m_usrLeaveName) & type=1)/用户登录时 就删除离线列表框中的用户名UINT nIndex;nIndex=m_ListClose.FindString(-1,m_usrLeaveName);/为-1,从头查找整个列表框m_ListClose.DeleteString(nIndex); int StringCount = m_ListClose.GetCount();/这段代码 是得到离线列表框的 用户for (int i=0; iclist-GetHeadPosition(); /得到list中首元素的位置while(pos != NULL)pSock = (CClientSocket *)pSocket-clist-GetNext(pos); /返回下一个元素的CObject*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(); /获得列表首元素的POSITIONwhile(po != NULL)pSock = (CClientSocket *)pSocket-clist-GetNext(po);pSock-Send(char *)&head, sizeof(Header); /向客户端发送离线用户列表pSock-Send(LPCTSTR)user_info, user_info.GetLength();CString CChatServerDlg:InsertLeaveMsg(CString str)CString array3;int k = 0; /k用于标志数组array的当前单元for( int i=0; iOpen(Provider=Microsoft.Jet.OLEDB.4.0;Data Source=students.mdb,adModeUnknown);m_pRs.CreateInstance(_uuidof(Recordset);m_pRs-Open(select * from table1,_variant_t(IDispatch *)m_pCon,true),adOpenStatic,adLockOptimistic,adCmdText);while(!m_pRs-adoEOF)vFieldValue = m_pRs-GetCollect(strName); strFieldValue = (LPCTSTR)_bstr_t(vFieldValue);if (strFieldValue = array0) /目的主机名m_pRs-PutCollect(sourceName, _variant_t(array1); /保存源主机名m_pRs-PutCollect(leaveMessage,_variant_t(array2); /保存消息内容m_pRs-MoveNext(); m_pRs-Close(); return strFieldValue;CString CChatServerDlg:QueryLeaveMsg(CString str)CString strSourceName;CString strLeaveMsg;/初始化环境:CoInitialize(NULL);/创建并打开数据库连接对象_variant_t vFieldValue;CString strFieldValue;m_pCon.CreateInstance(_uuidof(Connection);m_pCon-Open(Provider=Microsoft.Jet.OLEDB.4.0;Data Source=students.mdb,adModeUnknown);m_pRs.CreateInstance(_uuidof(Recordset);m_pRs-Open(select * from table1,_variant_t(IDispatch *)m_pCon,true),adOpenStatic,adLockOptimistic,adCmdText);while(!m_pRs-adoEOF)vFieldValue = m_pRs-GetCollect(strName); strFieldValue = (LPCTSTR)_bstr_t(vFieldValue); if(strFieldValue=str)vFieldValue = m_pRs-GetCollect(sourceName); /得到 源主机名 是谁发过来的消息strSourceName = (LPCTSTR/*char*/)_bstr_t(vFieldValue);vFieldValue = m_pRs-GetCollect(leaveMessage);strLeaveMsg = (LPCTSTR/*char*/)_bstr_t(vFieldValue); m_pRs-MoveNext();/移动到下一条记录m_pRs-Close(); /关闭数据库return (&+strSourceName+&+strLeaveMsg+&);void CChatServerDlg:OnStart() / TODO: Add your control notification handler code hereASSERT(IDM_ABOUTBOX & 0xFFF0) = IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX AppendMenu(MF_SEPARATOR);pSysMenu-AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);/ Set the icon for this dialog. The framework does this automatically/ when the applications main window is not a dialogSetIcon(m_hIcon, TRUE);/ Set big iconSetIcon(m_hIcon, FALSE);/ Set small icon/ TODO: Add extra initialization hereUpdateData(FALSE);:CoInitialize(NULL);/创建并打开数据库连接对象_variant_t vFieldValue;CString strFieldValue;CString str;int num=0; /定义数据库中 账号的个数m_pCon.CreateInstance(_uuidof(Connection);m_pCon-Open(Provider=Microsoft.Jet.OLEDB.4.0;Data Source=students.mdb,adModeUnknown);m_pRs.CreateInstance(_uuidof(Recordset);m_pRs-Open(select * from table1,_variant_t(IDispatch *)m_pCon,true),adOpenStatic,adLockOptimistic,adCmdText); while(!m_pRs-adoEOF)vFieldValue = m_pRs-GetCollect(strName); strFieldValue = (LPCTSTR)_bstr_t(vFieldValue);str += strFieldValue + &;num+;m_pRs-MoveNext();m_pRs-Close();CString array20;int k = 0; /k用于标志数组array的当前单元for( int i=0; istr.GetLength(); i+ ) /i用于记录str变量的当前字符if(i != (str.GetLength() - 1)if ( stri=& )k +;elsearrayk = arrayk + stri; for (int n=0; nReplaceSel(服务器初始化成功.rn);GetDlgItem(IDC_START)-EnableWindow(false);return; 5.1.2客户端的实现代码a. AskDlg类void CAskDlg:OnOK() / TODO: Add extra validation hereUpdateData();if(m_Nick=|m_Pass=|m_PassAgain=) AfxMessageBox(用户名或密码不能为空,请再次输入!);return; if(m_Pass!=m_PassAgain) AfxMessageBox(前后输入的密码不一致,请再次输入!);return;/-编辑用户信息并存储到一个字符串里- CString str;/-获取性别- CString strSex;UINT nID=GetCheckedRadioButton(IDC_RADIO_MAN,IDC_RADIO_WOMAN);GetDlgItemText(nID,strSex);/AfxMessageBox(m_Country);if(m_RealName=) m_R
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 农产品品牌IP创新创业项目商业计划书
- 输油工艺基础知识培训课件
- 2025年消费与零售行业深度报告:虚拟现实在零售体验中的创新
- 2025年绿色供应链管理在摩托车制造业的应用与推广案例分析报告001
- 2025年工业互联网平台入侵检测系统架构优化与升级报告
- 2025年工业互联网平台量子密钥分发技术在工业控制领域的应用与挑战
- 现代素食餐厅科普知识培训课件
- 江苏省泰州市2026届化学高三上期末检测模拟试题含解析
- 广东省阳山中学2026届化学高一上期末质量检测试题含解析
- 2025年考研英语(一)阅读理解长篇阅读词汇突破与真题答案
- 巡察整改工作课件模板
- 2025年城镇燃气条例竞赛题库
- GB/T 22030-2025车用乙醇汽油调合组分油
- 肺癌的护理新进展
- 2025年煤炭矿山职业技能鉴定考试-综采考试历年参考题库含答案解析(5套100道单选题合辑)
- 供电公司保密培训课件
- 车务段安全培训课件
- DB42T 1891-2022 人防工程防护及防化通风设备安装标准
- 2025发展对象考试题及答案
- DB4406T 55-2025 居家养老紧急呼援服务规范
- 业务咨询公司管理制度
评论
0/150
提交评论