作者简介作者简介:李伊林(1984-),男,江西省水利科学研究院助理工程师,研究方向为网络通信;傅小英(1987-),女,南昌大学信息工程学院硕士研究生,研究方向为计算机应用。1qt简介
qt是一个跨平台的c++图形用户界面库,由挪威trolltech公司于1995年底出品。qt的对象间通信采用信号/槽(signal/slot)机制,其中signal犹如mfc中的事件,而slot则是响应事件的方法。如果要实现对象间的通信,只需要把一个对象的slot和另一个对象的signal连接起来即可实现事件驱动[1]。
由于本系统是通过qt[2]图形开发工具来实现与用户之间的接口设计,所以在eclipse中如果要使用qt,则需添加qt插件方可建立qt gui工程文件。
2系统总体设计
本系统实现了linux系统下的简单通信,同时可以动态刷新在线用户列表,并与其他用户进行聊天通信或传送文件等[3]。如果用户想与其中某位好友聊天,则应该与其建立连接,此时两个客户端有一个作为服务器,另一个作为客户端。本系统的主要架构如图1所示。
系统主要分为客户端和服务器,服务器并不对用户发过来的信息进行转发操作,因为该做法会增加服务器的工作量。它只负责监听客户端的连接请求,同时,在与客户端建立新连接时,服务端会对客户端的端口号进行注册,之后将端口信息提供给每个连接上的客户端[4]。因而两个客户端之间的通信则不需要以服务器作为转发站,而是可以直接进行通信,从而减少了用户之间的通信响应时间。客户端主要可以进行注册、查找密码、添加/删除好友等一些基本操作[5],与好友建立连接之后,还可与好友进行聊天,互传文件等。
图1系统架构
3关键技术实现
3.1客户端listfriend类实现
listfriend类主要用来显示当前用户的好友列表,并按好友的不同组号将其进行分类。同时,用户可以通过触发右键事件对自己的好友列表进行修改,如添加、删除、移动好友,修改好友备注,修改用户信息等。在该类中,用户还要对自己的端口号进行监听,如果有好友提出聊天请求,用户可以根据自己的意愿接受或拒绝。或者用户自己向好友提出聊天请求,如果好友拒绝,则关闭对话框[6]。
listfriend类的主要实现方法如下:
listfriend::listfriend(qwidget *parent,user *a_user):qdialog(parent)
{// 右键菜单设置
familyitem = new qaction(tr("移动到家人"),this);
connect(familyitem,signal(triggered()),this,slot(movefamilygrpslot()));
………………………………………………………………
//右键二级菜单
grp1 = new qactiongroup(this);
grp1->addaction(frienditem);
grp1->addaction(familyitem);
grp1->addaction(stuitem);
//为listview控件绑定事件(单键事件、双键事件),以及其它控件的事件绑定(下拉列表、查找按钮、查找好友等)
connect(familylistview, signal(itemclicked(qlistwidgetitem *)), this, slot(getfrinum(qlistwidgetitem *)));
……………………………
//定时器初始化
time = new qtimer();
connect(time,signal(timeout()),this,slot(updatelistslot())); //刷新列表定时向host发送信息
connect(time,signal(timeout()),this,slot(sendmsgtohost())); //定时向host发送信息
time->start(10000);//10s
3.2客户端chatting类实现
chatting类是用户与好友进行聊天的窗口,用户之间可以发送信息:
chatting::chatting(qwidget *parent, qstring usernum, qstring frinum) : qdialog(parent)
{
//向好友发送连接请求 connect to the client
clientsocket = new qtcpsocket(this);
qhostaddress serverip("127.0.0.1");
clientsocket->connecttohost(serverip,(frinum.right(5)).toint());
//信号与槽的绑定:涉及的相关操作有连接、接收以及进度条
connect(clientsocket,signal(connected()),this,slot(clientconnected()));
connect(clientsocket, signal(byteswritten(qint64)),this, slot(updateclientprogress(qint64))); // 更新进度条
……………………………………………………
}
其中filedialogslot()、getfileslot()两个方法是对文件对话框的操作,sendslot()是向对方发送信息或文件的触发按钮,若只是发送信息,则可直接发送给对方。若是发送文件,则应先发送文件头,将文件名和文件大小发送给对方;clientrecvdata()是接收对方发过来的信息,对信息进行解析,并对其分类处理。其中接收到的消息类型有:对方拒绝聊天、普通信息、文件头、文件内容等。
3.3服务端server类
server类是服务器的主程序,它对incommingconntection()方法进行了重写,主要用于监听服务器端口,如果有请求到来,则实例化一个serverthread对象,用一个单独的线程处理与客户端的通信[7]。
void server::incomingconnection( int socketdescriptor)
{ //有请求到来时,则执行该函数,参数为其套接字描述符
qwarning()<< "new connection is comming" << socketdescriptor;
serverthread *thread = new serverthread(0,socketdescriptor);
connect(thread, signal(finished()), thread, slot(deletelater()));
thread->start(); //为每个客户端创建一个新线程
}
4结语
本文将qt作为图形界面开发工具,并利用qt socket通信原理以及多线程技术[8],以c++作为编程语言,设计并实现了在linux环境下的即时通信系统。通过系统的运行与测试,证明其可以有效地让客户之间直接通信,而不需要通过服务器作为通信中转点。之后的研究方向将着重于安全性方面,包括如何在此系统框架上提高通信安全性,以及如何提升用户之间的通信效率等。
参考文献参考文献:
\[1\]丁静.基于socket和消息队列的中后台接口通迅软件的设计[j].大连民族学院学报,2006,32(3):6567.
[2]葛福鸿,刘晓英,张丽萍.基于socket技术的即时通信软件的设计与实现[j].电脑开发与应用,2011,24(5):6365.
[3]戴元军.linux系统下的网络编程技术[j].应用技术,2001,28(6):2930.
[4]张彦春. 面向通信行业的嵌入式软件开发平台设计与实现[d].合肥:合肥工业大学,2006:5860.
[5]孙玉钰.基于p2p网络的聊天系统的研发[j].长春大学学报,2006,16(2):6165.
[6]马丹,李毅超,杨国纬.即使通信系统中动态群组聊天的实现[j].中国测试技术,2006,32(1):98100.
[7]倪继利.qt及linux操作系统窗口设计[m].北京:电子工业出版社,2006:218236.
[8]张志佳,于立国,李海滨,等.基于多线程的linux下并发服务器的实现研究[j].