基于QT局域网聊天系统设计毕业论文.docx
《基于QT局域网聊天系统设计毕业论文.docx》由会员分享,可在线阅读,更多相关《基于QT局域网聊天系统设计毕业论文.docx(39页珍藏版)》请在冰豆网上搜索。
基于QT局域网聊天系统设计毕业论文
基于QT的网络聊天系统设计
摘要
越来越多的嵌入式终端需要一个图形化的接口界面,良好的人机交互界面是嵌入式系统设计的一个关键技术。
特别是嵌入式的手持设备,比如手机,笔记本电脑等。
它对于嵌入式的实用性,美观性,和娱乐性都提供了极大地帮助,随着科学技术的高速发展,移动手持设备的网络功能已经非常成熟了,人们对手持设备网络软件的需求也日益增加,开发基于嵌入式终端的网络聊天系统软件具有很大的使用意义和价值。
本文的目标是实现基于QT的网络聊天系统设计,论文开始接受了Linux的优点和QT用于开发嵌入式图形界面的优点,着重分析了QT在软件开发中的编程机制。
并根据嵌入式应用的特点对嵌入式终端下的网络聊天系统进行了需求分析,概要设计,详细设计。
最后对关于论文的进一步的改进方向进行了简要的分析。
本文讨论的内容采用QT软件进行图形界面设计,利用软件自带的库,实现软件界面的设计,
本次研究实现类似于QQ的网络聊天方式,多个客户端可同时登陆服务器,并且客户端之间可进行通信。
关键词:
嵌入式;QT;网络聊天
Abstract
中文摘要
英文摘要
引言
第一章Linux和QT的简介
第二章软件需求分析
第三章网络聊天系统的概要设计
第四章网络聊天系统的详细设计
第五章系统测试
第六章系统运行和维护
第七章结语
第八章参考文献
第九章附录
第十章后记
引言
随着嵌入式产品的高速发展,大多数嵌入式操作系统拥有网络和图形界面的工程。
利用源代码开发的Linux搭建的嵌入式操作系统,拥有Linux具有开源,完全免费,和其强大的网络功能,越来越多的嵌入式产品都采用Linux操作系统。
它能提供全功能的桌面计算,并且支持大多数嵌入式操作系统上使用的芯片,包括ARM,PowerPC和MIPS等。
在嵌入式上使用轻量级,高性能,高可靠,可配置的GUI系统成为可行的解决方案。
虽然市场上出现了许多优秀的图形界面可发软件,但是随着计算机技术的高速发展,当新硬件,新技术出现时,计算机的体系结构,,指令系统,和操作系统都可能发生相应的变化,这势必会导致一部分应用软件在新的平台上无法运行,可移植性不行,但是QT基于跨平台的特点,它能解决这个问题,极大地提高了应用程序的可移植性。
因此,利用Linux做基于Qt的嵌入式聊天系统的开发是一个非常有意义的课题,具有非常重要的研究和商业价值。
第一章Linux和QT的简介
1.1Linux的主要特性
(1)符合POSIX1003.1标准
POSIX1003.1标准定义了一个最小的Unix操作系统接口,任何操作系统只有符合这一标准才能运行Unix程序。
(2)支持多用户访问和多任务编程
Linux是一个多用户操作系统,它允许多个用户同时访问系统而不会造成用户之间的干扰。
另外,LInux还支持多用户编程,一个用户可以创建多个进程,并使它们协同工作以完成用户的需求。
(3)采用页式存储管理
页式管理使Linux能更有效的利用物理存储空间,页面的换入换出为用户提供更大的存储空间。
(4)支持动态链接
用户的程序的执行往往离不开标准库的支持,多数操作系统一般采用静态链接方式--即在编译阶段就把用户程序和标准库链接好,这样当用多个进程运行时,可能会造成库代码在内存中有多个副本而浪费空间。
而Linux支持动态链接方式--即用户程序在运行阶段才把库链接进来,这样就能保证库代码在内存中时唯一的,可以节省内存空间。
(5)支持多文件系统
Linux支持多文件系统,目前支持的文件系统有:
EXT2,EXT3,XIAFS,ISOF,MSDOS,UMSDOS,PROC,NFS,SYSV,MINIX,SMB,UFS,NCP,VFAT等。
Linux最常用的文件系统是EXT2,它的文件名程度可达255个字节。
(6)支持TCP/IP,SLIP和PPP协议
在Linux中用户可以使用所有的网络服务,如NFS,telnet等。
SLIP和PPP能支持串行线上的TCP/IP协议的使用,这意味着用户可用一个高速的调制解调器(Modem)通过电话线连入Internet网中。
1.2QT的主要特性
QT是一个跨平台的C++GUI应用构架,它提供了丰富的窗口部件集,具有面向对象、易于扩展、真正的组建编程等特点,更引人注目的是目前Linux上最流行的KDE桌面环境就是建立在QT库的基础上的。
QT支持一下平台:
MS/WINDOWS-95、98、NT和2000;UNIX/X11-Linux、SunSolaris、HP-UX、DigitalUnix、IBMAIX、SGIIRIX;EMBEDDED-支持framebuffer的Linux平台.
信号和槽机制是QT编程的核心机制。
信号和槽是一种高级接口,应用于对象之间的通信,它是QT的核心机制也是QT区别于其它工具包的重要地方。
Qt具有跨桌面和嵌入式操作系统的移植性。
使用Qt只需一次性开发应用程序,就可跨不同桌面和嵌入式操作系统进行部署,而无须重新编写源代码。
具有跨平台IDE 的集成开发工具:
QtCreator是专为满足Qt开发人员需求而量身定制的跨平台集成开发环境(IDE)。
QtCreator可在Windows、Linux/X11和MacOSX桌面操作系统上运行,供开发人员针对多个桌面和移动设备平台创建应用程序。
第二章软件需求分析
2.1系统客户要求
需求分析是软件开发中的一个重要步骤,它的基本任务就是要准确地分析出系统应用者的需要,以及系统目标必须具备哪些工程,这些工程必须准确的体现出用户的要求。
根据网络聊天系统的特点,它应该能实现即时通讯的功能。
客户端和服务器应该具有不同的功能,其中服务器的主要工程就是管理客户端的登陆信息,包括账号、密码、在线状况、昵称等,而客户端的主要功能就是实现能够连接服务器,注册用户,登陆服务器,并且能实现客户端之间的通信。
并随时更新用户的信息。
2.2网络聊天系统架构分析简介
网络聊天系统分为客户端和服务器两部分,其中服务器运行在PC机上,客户端可运行在开发板上,亦可运行在PC机上。
首先服务器开始监听,然后客户端通过注册,登陆服务器,然后客户端之间即可进行通信。
2.3网络聊天系统界面设计
(1)服务器界面如图1所示;
服务器提供了所有注册了的用户的用户名,密码,昵称和登录状态信息,方便对用户信息进行管理。
(2)客户端登录模块界面显示如图2所示;
客户端登录模块类似于QQ的登陆界面,只是它多了连接服务器的IP地址和端口号。
(3)客户端注册模块界面显示如图3所示;
客户端注册模块可以让新用户注册信息。
(4)客户端好友列表界面显示如图4所示;
好友列表模块显示用户好友和自己的用户名和登陆状态。
(5)客户端聊天界面如图5所示;
客户端聊天模块可以让用户与其他用户通信。
图1服务器主界面
图2客户端登录模块主界面
图3注册模块界面
图4好友列表界面
图5聊天界面
2.4网络聊天系统架构图
2.4.1服务器架构图
服务器结构图如图6所示:
图6服务器结构图
2.4.2客户端架构图
客户端结构图如图7所示:
图7客户端结构图
2.5系统开发目标
(1)实现好友登陆,当好友登陆或离开时,服务器能即时通知所有的在线用户。
(2)收发信息同步,当一个用户想其他的好友发送消息是,相应的用户能即时接受消息。
2.6开发环境
软件环境:
Ubuntu10.11
硬件环境:
1GB以上的CPU,500MB以上的内存
第3章网络聊天系统的概要设计
根据调查和研究,得到系统所要处理的数据流程如图8所示:
图8网络聊天系统数据流程图
3.1服务器的具体实现
(1)解决中文乱码的关键代码:
QTextCodec:
:
setCodecForCStrings(QTextCodec:
:
codecForName("utf-8"));
QTextCodec:
:
setCodecForLocale(QTextCodec:
:
codecForName("utf-8"));
QTextCodec:
:
setCodecForTr(QTextCodec:
:
codecForName("utf-8"));
其头文件为#include.
(2)使用数据库保持用户信息,需要用到如下库:
#include
#include
其中QSqlDatabase库代表一个数据库的连接,QSqlQuery提供了执行Sql命令的方法。
使用方式如下:
QSqlQueryquery;
Query.exec(“DROPTABLEscooter”);
数据库的操作还涉及到库QSqlTableModle,该类为单一的数据库表提供了可编辑的模型。
使用方法如下:
Model=newQSqlTableModle(this);
Modle->settable(“scooter”);
Model->setSort(Scooter_Name,Qt:
:
AscendingOrder);
Model->select();
(3)打开和关闭监听的关键技术:
当要用QString类型的变量保持IP地址和端口号信息时,可使用方法trimmed(),它可以去除最前面和最后面多输入的空格。
可以使用QMessageBox类来给出提示信息,例如:
QMessageBox:
:
critical(NULL,
tr(“Warnning”),tr(“error!
”));
(4)使用Udp协议来通信使用方法如下:
添加头文件#include
Udpsocket=newQUdpSocket(this);
If(!
udpsocket->bind(QHostAddress(ip),(quint16)port+1)){
QMessageBox:
:
critical(NULL,”Warnning”,”error!
”);
}
Connect(udpsocket,SIGNAL(readyRead()),this,SLOT(recvMsg()));
3.2客户端的具体实现
客户端主要有4个大模块界面:
登陆模块,注册模块,好友列表模块,通信模块。
下面对这4个模块分别进行概要的分析。
3.2.1登陆模块
可以使用resize方法来设置窗口的大小,从而实现显示部分窗口的功能,具体使用如下:
this->resize(366,231);
在登陆模块还有如下关键代码:
Socket->abort();
Socket->connectToHost(QHostAddress(ip),(quint16)port.toInt());
Connect(socket,SIGNAL(readyRead()),this,SLOT(recvmsg()));
其中abort()方法用来关闭套接字,并且重新设置套接字。
3.2.2注册模块
注册模块主要使用的关键技术是正则表达式,头文件是
#include
使用方式如下:
QRegExprx(“^[1-9]/{1,2}[0-9]{4,7}$”);
表示前面1到2个是1-9中的某个数,后面跟着的是4到7个0到9的数字。
其中^表示锁定开头,$表示锁定结尾。
具体使用如下:
QRegExprx(“^[1-9]{1,2}[0-9]{4,7}”);
Rx.setPatternSyntax(QRegExp:
:
RegExp);
If(!
rx.exactMatch(username))
{QMessageBox:
:
warning(NULL,tr(“warning”),tr(“usernameerror”));
}
3.2.3好友列表模块
好友表面模块主要是显示好友上线信息,和好友列表,使用Udp协议接受服务器带来的信息。
当双击某好友用户时,机会弹出与相应好友的对话框。
具体实现将在详细设计阶段说明。
3.2.4通信模块
通信模块是使用Udp协议进行通信的,因为它不必建立连接。
第四章网络聊天系统的详细设计
4.1服务器模块
服务器和客户端通信既有通过TCP/IP协议,也有通过UDP协议进行通信的。
其中用户下线和用户信息更新时使用UDP协议,而用户登录,注册时使用TCP协议,使用数据库保持用户信息。
/////////server.cpp文件////////////////////////////
#include"server.h"
#include"ui_server.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
Server:
:
Server(QSqlDatabase*db,QWidget*parent):
QMainWindow(parent),
ui(newUi:
:
Server)
{
ui->setupUi(this);
server=newQTcpServer(this);
this->setWindowTitle("JY2012_QQServer");
ui->pushButton_2->setText("StartListen");
ip.clear();
port.clear();
this->db=db;
displayView();
}
Server:
:
~Server()
{
deleteui;
}
////////////OpenListenorCloseListen////////////////////
voidServer:
:
on_pushButton_2_clicked()
{
ip.clear();
port.clear();
ip=ui->lineEdit->text().trimmed();//去除最前面和最后面多余的空格
port=ui->lineEdit_2->text().trimmed();
if(ui->pushButton_2->text()=="StartListen")
{
if(!
server->listen(QHostAddress(ip),(quint16)port.toUInt()))
{
QMessageBox:
:
critical(NULL,tr("Warning"),tr("Listenerror"));
}
else
{
connect(server,SIGNAL(newConnection()),this,SLOT(NewConnection()));
udpsocket=newQUdpSocket(this);
if(!
udpsocket->bind(QHostAddress(ip),(quint16)port.toUInt()+1))
{
QMessageBox:
:
critical(NULL,tr("Warning"),tr("bindudpsocketerror").arg(udpsocket->errorString()));
}
connect(udpsocket,SIGNAL(readyRead()),this,SLOT(readDatagrams()));
ui->pushButton_2->setText("StopListen");
ui->lineEdit->setEnabled(false);
ui->lineEdit_2->setEnabled(false);
}
}
elseif(ui->pushButton_2->text()=="StopListen")
{
server->close();
ui->pushButton_2->setText("StartListen");
ui->lineEdit->setEnabled(true);
ui->lineEdit_2->setEnabled(true);
}
}
voidServer:
:
NewConnection()
{
qDebug()<<"connected";
socket=server->nextPendingConnection();
connect(socket,SIGNAL(readyRead()),this,SLOT(recvMsg()));
}
voidServer:
:
recvMsg()
{
QByteArrayblock;
block=socket->readAll();
QDataStreamin(&block,QIODevice:
:
ReadOnly);
in.setVersion(QDataStream:
:
Qt_4_7);
quint16datagramSize;
QStringmsgType;
in>>datagramSize>>msgType;
qDebug()<if(msgType=="REGISTER")
{
QStringusername;
QStringpasswd;
QStringnickname;
QStringstate="off";
intflag=0;
in>>username>>passwd>>nickname;
qDebug()<QSqlQueryquery;//用来输入数据库命令的
if(!
(query.exec("selectusernamefromscooter")))
{
QMessageBox:
:
critical(NULL,"exec","Execfailed.(selectusernamefromscooter)");
return;
}
insertUser(username,passwd,nickname,state);
}
elseif(msgType=="LOGIN")
{
idList.clear();
nickList.clear();
stateList.clear();
QStringid;
QStringpasswd;
in>>id>>passwd;
qDebug()<<"id,passwd"<QSqlQueryquery;
if(!
(query.exec("SELECTusername,passwdFROMscooter")))
{
QMessageBox:
:
critical(NULL,"exec","Execfailed.");
return;
}
while(query.next())
{
if(query.value(0).toString()==id&&query.value
(1).toString()==passwd)
{
qDebug()<<"Userloginsuccess";
QSqlQueryquery2;
query2.exec("updatescootersetstate='on'whereusername=:
username");
query2.bindValue(":
username",id);
if(!
query2.exec())
{
QMessageBox:
:
critical(NULL,"error","execfailed(updatescootersetstate='on'whereusername=:
username)");
return;
}
query2.exec("selectusername,nickname,statefromscooter");
while(query2.next())
{
idList.append(query2.value(0).toString());
nickList.append(query2.value
(1).toString());
stateList.append(query2.value
(2).toString());
}
qDebug()<on_pushButton_clicked();//刷新列表
QStringmsgType="UPDATE";
QByteArrayblock;
QDataStreamout(&block,QIODevice:
:
WriteOnly);
out.setVersion(QDataStream:
:
Qt_4_7);
out<<(quint16)0<out.device()->seek(0);
out<<(quint16)(block.size()-sizeof(quint16));
socket->write(block);
//发送更新信息给所有的同一网段用户
udpsocket->writeDatagram(block.data(),block.size(),
QHostAddress:
:
Broadcast,6666);
return;
}
}
if(!
query.next())
{
QStringmsgType="LOGIN_FAILED";
QByteArrayblock;
QDataStreamout(&block,QIODevice:
:
WriteOnly);
out.setVersion(QDataStream:
:
Qt_4_7);
out<<(quint16)0<out.device()->seek(0);
out<<(quint16)(block.size()-sizeof(quint16));
socket->write(block);
return;
}
}
}
boolServer:
:
openDB()
{qDebug()<<111;
qDebug()<<222;
db->setDatabaseName("scooters.dat");
qDe