收藏 分销(赏)

张依-16-河北金融学院信息管理与工程系课程设计报告.doc

上传人:精*** 文档编号:3418497 上传时间:2024-07-05 格式:DOC 页数:26 大小:817.50KB
下载 相关 举报
张依-16-河北金融学院信息管理与工程系课程设计报告.doc_第1页
第1页 / 共26页
张依-16-河北金融学院信息管理与工程系课程设计报告.doc_第2页
第2页 / 共26页
张依-16-河北金融学院信息管理与工程系课程设计报告.doc_第3页
第3页 / 共26页
张依-16-河北金融学院信息管理与工程系课程设计报告.doc_第4页
第4页 / 共26页
张依-16-河北金融学院信息管理与工程系课程设计报告.doc_第5页
第5页 / 共26页
点击查看更多>>
资源描述

1、.河北金融学院信息管理与工程系课程设计报告题 目: 局域网聊天工具 学生姓名: 张依 学 号: 20111811016 系别班级:信息管理与工程系11级计算机科学与技术本科班 专业(方向): 计算机科学与技术 指导者教师: 姜志旺 完 成 时 间: 2013年 5 月 16 日目录1. 任务与要求31.1设计任务 31.2具体要求 32. 系统总体设计42.1 设计目标及完成功能42.2 系统结构设计43. 系统详细设63.1窗口设计73.2接收消息模块163.3用户信息184测试205课程设计与总结256参考文献25 1 任务与要求11设计任务本课程设计是利用可视化编程库QT进行一个可视化的

2、网络通信程序设计,主要采用QUdpSocket、QTcpSocket、QTcpServer等类。1.2具体要求1.2.1系统的需求分析 能够发送消息到不同的用户程序。 用户程序能够接收来自不同用户程序的消息,并能识别出是哪个用户。 通过协议可以找到局域网里面的用户。 根据具体情况进行发挥,努力完善网络通讯程序。1.2.2 完成系统设计找出系统的对象,抽象完成分析类图的创建,根据情况画出顺序图,协作图,状态图,部署图,组件图,活动图。针对具体的思想语言要求写出具体的实现类图,类的属性和服务,标出类之间的关系。1.2.3编码完成需要编码完成的模块。1.2.4测试编写合适的测试用例完成系统的测试工作

3、并分析结果2 系统总体设计21系统设计目标及完成功能本项目的设计目标为一个高性能的,易于使用的,面向校园内部通信需求的局域网即时通信软件。它应具有如下特征: 1、具有高性能,可同时处理多个连接请求。2、对硬件要求低,适应范围广,运行稳定。 3、具有一定的容错性能。当用户登入聊天室时,用户输入的内容直接发送到其他有登入此聊天室的用户,用户与用户直接通信不需要经过服务器。最终的软件产品应具有如下功能:(1) 能够随时改变自己的昵称。(2) 能够自动更新其他用户的名单及在线人数。(3) 随时获取系统的当前时间。(4) 能够向其他用户传输文件。(5) 能够保存或者删除聊天记录。(6) 能够改变聊天的字

4、体。(7) 能够多人聊天。(8) 只限于局域网内聊天。(9) 美观的操作界面。 (10) 主界面显示聊天信息,在线用户信息。22 系统结构设计进入用户界面软件构架处理新用户加入显示用户信息显示新用户信息发送文件进入聊天室退出用户操作系统显示用户离开删除用户信息显示新用户信息用户处理处理用户离开处理新用户加入接受文件保存聊天记录文件处理聊天记录发送文件删除聊天记录发送信息接受信息发送信息聊天室活动图处理用户离开处理新用户加入处理文字消息处理下划线颜色加粗接受消息发送消息3 系统详细设计3.1窗口设计私聊窗口设计群聊窗口设计3.1.1聊天室窗口设计聊天室窗口分为三个模块,模块一:发送消息;模块二:

5、接收消息;模块三:接收在线用户的信息如(用户名、主机名、IP地址)。1、模块一也可以称为用户发言区。专门用来处理用户所输入的发言等,可以对发言的字体大小,字体和颜色,粗体,下划线进行更改以及保存聊天记录、清屏等功能。用户发言后直接点击发送按钮,此时就会调用发送函数sendMessage(),将messageTextEdit组件中的内容发送出去。通过QByteArray型局部变量datagram中构建待发送的数据包,然后通过QUdpSocket类的 writeDatagram ( const QByteArray & datagram, const QHostAddress & host, qu

6、int16 port );函数将数据包发出。值得注意的是,这里的地址使用了QHostAddress:Broadcast值,它对应IPv4下的广播地址,如果将该值更换成单机地址(如本机地址QHostAddress:LocalHost),将变成一个普通的点对点的UDP程序。发送函数实现的主要代码如下:void siliao:sendMessage(MessageType type , QString serverAddress) /发送信息 QByteArray data; /定义一个存储数据的容器 QDataStream out(&data,QIODevice:WriteOnly); /将数据转

7、化为同一类型QString localHostName = QHostInfo:localHostName(); /获取主机名 QString address = getIP(); /获取IP地址 out type getUserName() textEdit-toPlainText() = ) QMessageBox:warning(0,tr(警告),tr(发送内容不能为空),QMessageBox:Ok); return; message = getMessage(); out address textBrowser-verticalScrollBar()-setValue(ui-text

8、Browser-verticalScrollBar()-maximum(); break; xsiliao-writeDatagram(data.data(),data.size(),QHostAddress:QHostAddress(xpasvuserip), 45457); /将data容器中的数据发送出去字体设置实现字体样式转变设置实现的主要代码如下:void qunliao1:currentFormatChanged(const QTextCharFormat &format) ui-fontComboBox-setCurrentFont(format.font(); if (form

9、at.fontPointSize() comboBox-setCurrentIndex(3); else ui-comboBox-setCurrentIndex(ui-comboBox -findText(QString:number(format.fontPointSize(); color = format.foreground().color();字体加粗样式设置实现的主要代码如下:void qunliao1:on_boldToolBtn_clicked(bool checked) if(checked) ui-messageTextEdit-setFontWeight(QFont:Bo

10、ld); else ui-messageTextEdit-setFontWeight(QFont:Normal); ui-messageTextEdit-setFocus();字体添加下划线样式设置实现的主要代码如下:void qunliao1:on_underlineToolBtn_clicked(bool checked) ui-messageTextEdit-setFontUnderline(checked); ui-messageTextEdit-setFocus();清屏功能实现的主要代码如下:void qunliao1:on_clearToolBtn_clicked() ui-me

11、ssageBrowser-clear(); 改变字体颜色实现的主要代码如下:void qunliao1:on_toolButton_clicked() color = QColorDialog:getColor(color, this); if (color.isValid() /判断是否创建对象实例,创建了就进入 ui-messageTextEdit-setTextColor(color); ui-messageTextEdit-setFocus(); 保存聊天记录的主要代码如下:void qunliao1:on_saveToolBtn_clicked() if (ui-messageBro

12、wser-document()-isEmpty() QMessageBox:warning(0, tr(警告), tr(聊天记录为空,无法保存!), QMessageBox:Ok); else QString fileName = QFileDialog:getSaveFileName(this, tr(保存聊天记录), tr(聊天记录), tr(文本(*.txt);All File(*.*); if(!fileName.isEmpty() saveFile(fileName); bool qunliao1:saveFile(const QString &fileName) QFile fil

13、e(fileName); if (!file.open(QFile:WriteOnly | QFile:Text) QMessageBox:warning(this, tr(保存文件), tr(无法保存文件 %1:n %2).arg(fileName) .arg(file.errorString(); return false; QTextStream out(&file); out messageBrowser-toPlainText(); return true;3.1.2发送文件窗体设计发送文件窗体中包涵了一些简单的组件,其中最主要的就是发送按钮,他实现了文件的传输。1、用户在界面按下打

14、开按钮后,openFile()槽函数将被调用。该函数通过Qt文件选择对画框QFileDialog所提供的静态函数getOpenFileName(),能够很容易地返回用户所选取的文件名,这里将其保存在私有成员变量fileName中。如果选中返回的文件名非空,将激活发送按钮。单击发送按钮就开启监听,并且等待接收者接受。当接收者接受时就开始建立连接。 一旦连接建立成功,QTcpServer类将发出newConnection ()消息,继而调用sendMessage()槽函数。该函数首先向接收方发送一个文件头结构。文件头结构由三个字段组成,分别是64位的总长度(包括文件数据长度和文件头自身长度),64

15、位的文件名长度和文件名。函数sendMessage()首先以只读方式打开选中的文件,然后通过QFile类的size()函数获取待发送文件的大小,并将该值暂存于TotalBytes变量中。 接下来将发送缓冲区outBlock封装在一个QDataStream类型的变量中,这样做可以很方便的通过重载的操作符填写文件头结构。设置文件头结构的操作有些小技巧,这里首先通过QString类的right()函数去掉文件的路径部分,仅将文件部分保存在currentFile变量中,然后通过sendOut qint64(0) qint64(0) seek(0)函数将读写操作指向从头开始,并且调用类似操作sendOu

16、t TotalBytes nextPendingConnection(); /nextPendingConnection获得socket 连接; connect(clientConnection, SIGNAL(bytesWritten(qint64), this, SLOT(updateClientProgress(qint64); ui-serverStatusLabel-setText(tr(开始传送文件 %1 !).arg(theFileName); localFile = new QFile(fileName); if(!localFile-open(QFile:ReadOnly)/

17、以只读方式打开 QMessageBox:warning(this, tr(应用程序), tr(无法读取文件 %1:n%2) .arg(fileName).arg(localFile-errorString(); return; TotalBytes = localFile-size(); /此时总大小为实际文件大小 QDataStream sendOut(&outBlock, QIODevice:WriteOnly);/将数据写入outBlock缓存; sendOut.setVersion(QDataStream:Qt_4_7); time.start(); / 开始计时 QString cu

18、rrentFile = fileName.right(fileName.size() - fileName.lastIndexOf(/)-1); sendOut qint64(0) qint64(0) seek(0); /返回到数据缓冲区outBlock的起始地址 sendOut TotalBytes write(outBlock); outBlock.resize(0);更新进度条的代码如下: qApp-processEvents(); bytesWritten += (int)numBytes; if (bytesToWrite 0) outBlock = localFile-read(q

19、Min(bytesToWrite, payloadSize); /每次发送payloadSize大小的数据 bytesToWrite -= (int)clientConnection-write(outBlock); outBlock.resize(0); /清空发送缓冲区 else localFile-close(); ui-progressBar-setMaximum(TotalBytes); ui-progressBar-setValue(bytesWritten); float useTime = time.elapsed(); double speed = bytesWritten

20、/ useTime; ui-serverStatusLabel-setText(tr(已发送 %1MB (%2MB/s) n共%3MB 已用时:%4秒n估计剩余时间:%5秒) .arg(bytesWritten / (1024*1024) .arg(speed*1000 / (1024*1024), 0, f, 2) .arg(TotalBytes / (1024 * 1024) .arg(useTime/1000, 0, f, 0) .arg(TotalBytes/speed/1000 - useTime/1000, 0, f, 0); if(bytesWritten = TotalByte

21、s) localFile-close(); tcpServer-close(); ui-serverStatusLabel-setText(tr(传送文件%1成功).arg(theFileName); 1、添加所需要的组件主要组件名称及用途如下:progressBar进度条,用于显示数据传输的过程serverOpenBtn打开本地文件serverSendBtn发送文件serverCloseBtn关闭窗体2、重要组件QTcpServer的使用(1) 创建对象tcpServer。(2) 通过tcpServer关联信号和槽。(3) 每当发现新连接时信号newConnection就会触发槽函数send

22、Message()实现文件的发送。tcpServer组件中的nextPendingConnection()方法是用来获得socket 连接的。3.1.3接收窗体设计 接收窗体中也是一些简单的组件,其主要的功能还是在于文件接收的函数中。1、当接收到其他用户发来的文件接收请求时,用户可以接受请求,也可以拒绝请求。当接收请求后,newConnect()函数将被调用。该函数的主要功能是连接服务器,它使用了QTcpSocket类的connectToHost()函数,其中的两个参数分别是服务器主机地址及其监听端口。 接收程序tcpclient完成的功能与发送程序恰恰相反,它负责从TCP连接上接收数据,并将

23、其写入当前目录下的指定文件中。其界面也是一个简单的对话框,上面布置一个QProgressBar进度条,一个用来显示状态的QLabel,两个QPushButton按钮分别用来取消接收和退出程序。 当建立的连接有新的可供读取的数据时,QTcpSocket类会发出readyRead()信号,从而触发readMessage()槽函数。该函数完成数据的接收、存储,并更新进度显示。 首先将返回的TCP连接tcpClient封装的QDataStream类型变量in中,同时设置流化数据格式类型为QDataStream:Qt_4_6,与客户端保持一致。现在可以很方便的通过重载后的bytesAvailable()

24、 = sizeof(qint64)*2) & (fileNameSize =0)操作确保至少有16字节的可用数据且文件名长度为0(表示未从TCP连接接收文件名长度字段,仍处于第一步操作),然后调用in TotalBytes fileNameSize操作读取总共需接收的数据和文件名长度。(2)类似的通过(tcpServerConnection-bytesAvailable() = fileNameSize) & (fileNameSize !=0)操作确保连接上的数据已包含完整的文件名且文件名长度不为0(表示已从TCP连接接收文件名长度字段,处于第二步操作中),然后调用in fileName操作

25、读取文件名,并根据该文件名在本地以只写方式打开一个同名文件localFile,用来保存接收到的数据。接下来的工作是读取实际的文件数据并保存,以及更新进度显示,直到接收到完全的数据。由于所发送的文件内容自身也是无格式的流,因此在接收文件内容时,只要TCP连接上有数据,就调用tcpClient-readAll()操作将当前全部可读数据读入接收缓冲inBlock中,随后再将该缓冲中的数据写入文件localFile中。当已收到的数据bytesReceived等于TotalBytes时,接收完毕,这时通过tcpClient-close()操作关闭连接。接收文件的主要代码如下: QDataStream i

26、n(tcpClient); in.setVersion(QDataStream:Qt_4_7); float useTime = time.elapsed(); if (bytesReceived bytesAvailable() = sizeof(qint64)*2) & (fileNameSize = 0) inTotalBytesfileNameSize; bytesReceived += sizeof(qint64)*2; if(tcpClient-bytesAvailable() = fileNameSize) & (fileNameSize != 0) infileName; by

27、tesReceived +=fileNameSize; if(!localFile-open(QFile:WriteOnly) QMessageBox:warning(this,tr(应用程序),tr(无法读取文件 %1:n%2.) .arg(fileName).arg(localFile-errorString(); return; else return; if (bytesReceived bytesAvailable(); inBlock = tcpClient-readAll(); localFile-write(inBlock); inBlock.resize(0); ui-pro

28、gressBar-setMaximum(TotalBytes); ui-progressBar-setValue(bytesReceived); double speed = bytesReceived / useTime; ui-tcpClientStatusLabel-setText(tr(已接收 %1MB (%2MB/s) n共%3MB 已用时:%4秒n估计剩余时间:%5秒) .arg(bytesReceived / (1024*1024) .arg(speed*1000/(1024*1024),0,f,2) .arg(TotalBytes / (1024 * 1024) .arg(us

29、eTime/1000,0,f,0) .arg(TotalBytes/speed/1000 - useTime/1000,0,f,0); if(bytesReceived = TotalBytes) localFile-close(); tcpClient-close(); ui-tcpClientStatusLabel-setText(tr(接收文件 %1 完毕) .arg(fileName); 1、 添加所需要的组件 一个lable,一个progressBar,两个pushButton。 主要组件名称及用途如下: progressBar进度条,用于显示数据接收的过程 tcpClientCan

30、cleBtn停止接收 tcpClientCloseBtn关闭窗体2、 重要组件QTcpSocket的使用(1) 创建对象tcpClient。(2) 通过tcpClient关联信号和槽。(3) 每当发送端将文件发送出来时,接收端就会设置服务器地址并通过tcpClient组件的connectToHost方法连接服务器,连接成功并发现有可接收的数据时,信号readyRead()就会触发槽函数readMessage(开始接收数据。每读取一个字节时tcpClient组件中的 bytesAvailable 属性增加一Tcpclient.uitcpserver.ui 3.2接收消息模块messageBrow

31、ser组件实现,接受数据函数首先调用QUdpSocket类的成员函数hasPendingDatagrams()以判断是否有可供读取的数据。如果有则通过pendingDatagramSize()获取当前可供读取的UDP报文大小,并据此大小分配接收缓冲区,最后读取相应数据。接收函数中几条主要语句如下:void qunliao1:qlprocessPendingDatagrams() while(udpSocket-hasPendingDatagrams() /判断是否有可供读取的数据 QByteArray datagram; /用于存放接收的数据报 datagram.resize(udpSocke

32、t-pendingDatagramSize(); /让datagram的大小为等待处理的数据报的大小,这样才能接收到完整的数据 udpSocket-readDatagram(datagram.data(), datagram.size(); /接收数据报,将其存放到datagram中; QDataStream in(&datagram, QIODevice:ReadOnly); / 从文件datagram中读取串行化的数据; int messageType; in messageType; QString userName,localHostName,ipAddress,message; QS

33、tring time = QDateTime:currentDateTime() .toString(yyyy-MM-dd hh:mm:ss); /获取系统时间 switch(messageType) case QLMessage: in userName localHostName ipAddress message; /数据的流向 ui-messageBrowser-setTextColor(Qt:blue); ui-messageBrowser-setCurrentFont(QFont(Times New Roman,12); ui-messageBrowser-append( +userName+ + time); /显示用户名和接收到数据的时间 ui-messageBrowser-append(message); /显示接收的消息 break; 3.3用户信息用userTableWidget组件实现,在userTableWidget中显示了用户的,用户名、主机名、IP地址。有新用户加入时就调用newParticipant()函数处理新用户,有用户离开时就会调用participantLeft()函数处理离开的用户。用户加入时会把自己的用户名、主机名、IP地址发送出去,其他用户就会接收到并将其内容显示在userTabl

展开阅读全文
相似文档                                   自信AI助手自信AI助手
猜你喜欢                                   自信AI导航自信AI导航
搜索标签

当前位置:首页 > 教育专区 > 其他

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

关于我们      便捷服务       自信AI       AI导航        获赠5币

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

客服电话:4008-655-100  投诉/维权电话:4009-655-100

gongan.png浙公网安备33021202000488号   

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

关注我们 :gzh.png    weibo.png    LOFTER.png 

客服