BT工具的设计和实现毕业论文最终修订版_第1页
BT工具的设计和实现毕业论文最终修订版_第2页
BT工具的设计和实现毕业论文最终修订版_第3页
BT工具的设计和实现毕业论文最终修订版_第4页
BT工具的设计和实现毕业论文最终修订版_第5页
已阅读5页,还剩57页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 上海复旦大学毕业设计(论文)用纸bt下载工具设计与实现摘 要bittorrent是当今internet上非常流行的基于p2p技术的内容分发系统,它能够快速、有效地在internet的网络结点上分发大的文件,而不会给源服务器带来过大负载。bittorrent协议是一个网络文件传输协议,它能够实现点对点文件分享的技术。bittorrent协议是用在对等网络中文件分享的网络协议程序,它是用户群对用户群,下载同一文件的人越多,且下载后,继续维持上传的状态,就可以分享,成为其用户端节点下载的种子文件,下载该档案的速度越快。本文的主要工作内容:深入研究了bittorrent协议及bittorrent协议

2、的工作原理,qt的信号与槽机制,种子文件的解析过程,客户端和tracker服务器通信,peer与peer之间的通信,dht网络的实现方法以及bt的关键学法和策略,对软件的系统设计进行论述。 关键字:bittorrent协议;信号与槽机制;torrent文件解析;iibt download tool design and realizationabstractbittorrent is very popular in today's internet-based p2p content distribution system technology, it is able to quick

3、ly and efficiently distribute large files over the network nodes of the internet, rather than the source server will bring excessive load. bittorrent protocol is a network file transfer protocol that enables peer file sharing technology. bittorrent protocol is used in peer to peer network file shari

4、ng network protocol procedures, it is the user group for users, download the same file more people, and after downloading, continue to maintain the status of the upload, you can share, as its clients node torrent file, download the file faster. the main content of the paper: in-depth study of the wo

5、rking principle of the bittorrent protocol and bittorrent protocol for communication, dht network qt signals and slots mechanism, the seed file parsing process, the client and server communications tracker, peer and peer between bt's key methods and the study of law and policy, the system design

6、 software are discussed.key words:the bittorrent protocol;signal and slot mechanism;torrent file parsing;目 录摘 要iabstractii1 绪论11.1 国内外bittorrent的发展状况11.2 发展bittorrent的目的和意义11.2.1 发展bittorrent的目的11.2.2 发展bittorrent的意义12 bittorrent的原理分析22.1 综述bittorrent的相关技术22.1.1 bittorrent协议22.1.2 bittorrent的专业术语22.

7、1.3 种子的解析32.1.4 bittorrent运行原理62.1.5 bittorrent下载流程72.1.6 bittorrent协议的发展72.2 bittorrent的软件要求82.2.1 软件系统设计要求82.2.2 软件系统实现83 需求分析103.1 种子文件解析功能分析103.2 tracker服务器功能分析103.3 torrent服务器功能分析103.4 软件需求分析104 概要设计114.1.1 种子解析模块114.1.2 连接模块114.1.3 peer管理模块114.1.4 出错处理模块114.1.5 窗口界面模块115 详细设计135.1 系统功能模块135.2

8、qt的信号与槽机制145.3 bt的算法与策略195.3.1 阻塞算法195.3.2 超级种子算法195.3.3 结束算法205.3.4 防冷落算法205.3.5 最佳无阻塞算法205.3.6 最稀有算法215.4 bt软件的模块的实现215.4.1 种子解析模块的实现2115.4.2 client与traceker通信模块的实现215.4.3 peer之间的通信模块的实现225.4.4 软件出错模块的实现225.4.5 下载任务状态的实现225.4.6 软件主界面模块的实现225.5 代码实现245.5.1 添加种子代码245.5.2 解析种子代码255.5.3 peer通信代码275.5.

9、4 窗体中任务代码276 系统测试326.1 测试概述326.2 测试特性326.3 测试种类33结论34参考文献35致谢36外文原文37中文翻译4921 绪论1.1 国内外bittorrent的发展状况说到bittorrent可能有人还不知道是什么东西,但是说到种子可谓是无人不知无人不晓啊!那么在这个下载过程是通过什么支撑的,或者说下载客户端与服务器之间是怎么预定通信的呢,那就是bittorrent协议,用来进行对种子文件管理和规范。bittorrent协议是一个网络文件传输协议,它能够实现点对点文件分享的技术。比起其他点对点的协议,它更有多点对多点的特性,这个特点简单的说就是:下载的人越多

10、,速度越快。下载完不马上关闭bittorrent软件,就可以成为种子即拥有完整的档案者分流让其他人下载,或者说bittorrent一种分发文件的协议。它通过url来识别内容,并且可以无缝的和web进行交互。它基于http协议,它的优势是:如果有多个下载者并发的下载同一个文件,那么,每个下载者也同时为其它下载者上传文件,这样,文件源可以支持大量的用户进行下载,而只带来适当的负载的增长。1.2 发展bittorrent的目的和意义1.2.1 发展bittorrent的目的 bittorrent是一种p2p模式,对于p2p模式相对c/s模式,具有很多优点,但是随着p2p应用的不断增多,p2p技术也开

11、始面临一些问题,例如路由效率低下、维护开销过大、系统稳定性差、安全性无法保证以及服务不可靠等问题。因此,在提高现有p2p网络资源定位的效率,降低其维护开销,增强p2p系统的稳定与安全性,提高p2p各个节点提供服务的可靠性等方面都需要做深入的研究。深入研究p2p资源定位技术有重要的理论和现实意义。一方面,随着p2p应用的不断增长,p2p资源定位技术遇到的一系列问题迫切需要我们对它进行更加深入的研究,这将有助于它的进一步推广和使用;另一方面,把p2p资源定位技术与其它的技术相结合,可以达到相互促进的效果,如把p2p资源定位技术引入到通讯领域,把p2p资源定位技术与网格技术相结合,都可以促进彼此的发

12、展。1.2.2 发展bittorrent的意义发展bittorrent的意义对于大多数网民是不言而喻的。在平时的生活或学习大多数下载是下载一些音乐,电影和一些软件,尤其是电影,现在是已经进入了高清时代,一部高清电影动辄几个g,在中国的平均网速相对发达国家相对较低的情况下,在以前没有bt技术前,要下载高清电影简直是想都不敢想,占有很高的带宽,文件大,下载时间延长,势必会影响其他工作,而有了bt的迅速发展,通过互联网用户下载这个影片的数量大大加增,下载用户越多,速度越快!甚至有些公司提供离线下载服务,公司通过强大的服务器先通过bittorrent协议把文件先下载到公司服务器,然后用户再从服务器取回

13、到本地,可靠且速度快。bitorrent技术广泛应用与电视直播,网络视频和在线游戏中。很多网络游戏的在线更新,比如说如魔兽世界就是采用bt的技术,所以当每次有改版时,动辄数百mb的更新包,通过游戏厂商所提供的更新程序,以bittorrent协议的方式进行下载分流。这为以往的其他种在线游戏,每次重大改版就必须重新压制光盘,或是等待单一下载点的下载方式,带来另一种节省成本的经营模式。2 bittorrent的原理分析2.1 综述bittorrent的相关技术2.1.1 bittorrent协议对于普通的httpftp下载使用tcp/ip协议,bittorrent协议是架构于tcp/ip协议之上的一

14、个p2p文件传输协议,处于tcp/ip结构的应用层。 bittorrent协议本身也包含了很多具体的内容协议和扩展协议,并在不断扩充中。根据bittorrent协议,文件发布者会根据要发布的文件生成提供一个.torrent文件,即种子文件,也简称为“种子”,可以通过一些种子软件进行种子文件生成。种子文件本质上是文本文件,文本的内容包含tracker信息和文件信息两部分。tracker信息主要是bt下载中需要用到的tracker服务器的地址和针对tracker服务器的设置,也就是下载软件通过解析种子文件,通过tracker信息然后和tracker建立连接,进行通信,从服务器获取到peer的列表,

15、即你从其他客户端下载文件时建立连接需要的信息,同时也把你的主机的信息上传到tracker供其他客户端下载。文件信息是根据对目标文件的计算生成的,即根据bittorrent协议内的bencode规则进行提供下载文件进行编码。主要是把提供下载的文件虚拟分成大小相等的块,块大小必须为2k的整数次方,由于是虚拟分块,硬盘上并不产生各个块文件,并把每个块的索引信息和hash验证码写入种子文件中,确保块不被重复下载所以,种子文件就是被下载文件的“索引”。下载时,bt客户端首先解析种子文件得到tracker地址,然后连接tracker服务器。tracker服务器回应下载者的请求,提供下载者其他下载者包括发布

16、者的ip。下载者再连接其他下载者,根据种子文件,两者分别告知对方自己已经有的块,然后交换对方所没有的数据。此时不需要其他服务器参与,分散了单个线路上的数据流量,因此减轻了服务器负担。下载者每得到一个块,需要算出下载块的hash验证码与种子文件中的对比,如果一样则说明块正确,不一样则需要重新下载这个块。这种规定是为了解决下载内容准确性的问题。一般的http/ftp下载,发布文件仅在某个或某几个服务器,下载的人太多,服务器的带宽很易不胜负荷,变得很慢。而bittorrent协议下载的特点是,下载的人越多,提供的带宽也越多,下载速度就越快。同时,拥有完整文件的用户也会越来越多,使文件的“寿命”不断延

17、长。为了解决某些用户“下完就跑”的现象,在非官方bittorrent协议中还存在一种慢慢开放下载内容的超级种子的算法。2.1.2 bittorrent的专业术语tracker:收集下载者信息的服务器,并将此信息提供给其他下载者,使下载者们相互连接起来,传输数据。种子:指一个下载任务中所有文件都被某下载者完整的下载,此时下载者成为一个种子。发布者本身发布的文件就是原始种子。也指.torrent文件。做种:发布者提供下载任务的全部内容的行为;下载者下载完成后继续提供给他人下载的行为。2.1.3 种子的解析如图所示为种子文件内容。图2-1 bt种子文件结构图bt种子文件使用了一种叫bencoding

18、的编码方法来保存数据。bencoding现有四种类型的数据:strings(字符串),integers(整数),lists(列表),dictionaries(字典)(1)strings(字符串)编码为:<字符串长度>:<字符串>例如:4:test 表示为字符串"test",表示长度为4个字节的字符串teststrings类型是没有没开始或结束标记(2)integers(整数)编码为:i<整数>e开始标记i,结束标记为e例如:i1234e 表示为整数1234 i-1234e 表示为整数-1234整数没有大小限制(3)lists(列表)编码为

19、:l<bencoding编码类型>e开始标记为l,结束标记为e列表里可以包含任何bencoding编码类型,包括整数,字符串,列表,字典。例如: l4:test5:abcdee 表示为二个字符串"test","abcde"(4)dictionaries(字典)编码为d<bencoding字符串><bencoding编码类型>e开始标记为d,结束标记为e关键字必须为bencoding字符串值可以为任何bencoding编码类型例如:d3:agei20ee 表示为"age"=20d4:path3:c:&

20、quot;8:filename8:test.txt表示为"path"="c:"","filename"="test.txt"(5)具体文件结构如下:全部内容必须都为bencoding编码类型。整个文件为一个字典结构,包含如下关键字announce:tracker服务器的url(字符串)announce-list(可选):备用tracker服务器列表(列表)creation date(可选):种子创建的时间,unix标准时间comment(可选):备注(字符串)created by(可选):创建人或创建程序

21、的信息(字符串)info:一个字典结构,包含文件的主要信息,分为单文件结构或多文件结构。单文件结构:length:文件长度,单位字节(整数)md5sum(可选):长32个字符的文件的md5校验(字符串)name:文件名(字符串)piece length:每个块的大小,单位字节(整数)pieces:每个块的20个字节的sha1 hash的值(二进制格式)多文件结构如下:files:一个字典结构length:文件长度,单位字节(整数)md5sum(可选):同单文件结构中相同path:文件的路径和名字,是一个列表结构name:最上层的目录名字(字符串)piece length:同单文件结构中相同pi

22、eces:同单文件结构中相同综上,多文件torrent的结构的树形图。图2-2 多文件结构图图2-3 单文件结构图2.1.4 bittorrent运行原理bt原理普通的http/ftp下载使用tcp/ip协议,bittorrent协议是架构于tcp/ip协议之上的一个p2p文件传输协议,处于tcp/ip结构的应用层。bittorrent协议本身也包含了很多具体的内容协议和扩展协议,并在不断扩充中。根据bittorrent协议,文件发布者会根据要发布的文件生成提供一个.torrent文件,即种子文件,也简称为“种子”。torrent文件本质上是文本文件,包含tracker信息和文件信息两部分。t

23、racker信息主要是bt下载中需要用到的tracker服务器的地址和针对tracker服务器的设置,文件信息是根据对目标文件的计算生成的,计算结果根据bittorrent协议内的b编码规则进行编码。它的主要原理是需要把提供下载的文件虚拟分成大小相等的块,块大小必须为2k的整数次方,由于是虚拟分块,硬盘上并不产生各个块文件,并把每个块的索引信息和hash验证码写入.torrent文件中;所以,种子文件就是被下载文件的“索引”。下载者要下载文件内容,需要先得到相应的.torrent文件,然后使用bt客户端软件进行下载。下载时,bt客户端首先解析.torrent文件得到tracker地址,然后连接

24、tracker服务器。tracker服务器回应下载者的请求,提供下载者其他下载者(包括发布者)的ip。下载者再连接其他下载者,根据.torrent文件,两者分别对方告知自己已经有的块,然后交换对方没有的数据。此时不需要其他扮演服务器参与,分散了单个线路上的数据流量,因此减轻了服务器负担。下载者每得到一个块,需要算出下载块的hash验证码与.torrent文件中的对比,如果一样则说明块正确,不一样则需要重新下载这个块。这种规定是为了解决下载内容准确性的问题。一般的http/ftp下载,发布文件仅在某个或某几个服务器,下载的人太多,服务器的带宽很易不胜负荷,变得很慢。而bittorrent协议下载

25、的特点是,下载的人越多,提供的带宽也越多,种子也会越来越多,下载速度就越快。而有些人下载完成后关掉下载任务,提供较少量数据给其他用户,为尽量避免这种行为,在非官方bittorrent协议中存在超级种子的算法。这种算法允许文件发布者分几步发布文件,发布者不需要一次提供文件所有内容,而是慢慢开放的下载内容的比例,延长下载时间。此时,速度快的人由于未下载完必须提供给他人数据,速度慢的人有更多机会得到数据。2.1.5 bittorrent下载流程在整个下载过程,tracker服务器一个不可缺少的角色,它不同的下载者之间搭了一个桥梁,下载者在下载开始以及下载进行的过程中,要不停的与tracker服务器进

26、行通信,以汇报自己的信息,并获取其它下载client的信息。这种通信是通过http协议进行的,又被称为tracker http协议,它的过程是这样的:client向tracker发一个http的get请求,并把它自己的信息放在get的参数中;这个请求的大致意思是:我是xxx,我想下载yyy文件,我的ip是aaa,我用的端口是bbb。tracker对所有下载者的信息进行维护,当它收到一个请求后,首先把对方的信息记录下来,如果已经记录在案,那么就检查是否需要更新,然后将一部分,并非全部,根据设置的参数已经下载者的请求参与下载同一个文件,一个tracker服务器可能同时维护多个文件的下载,的下载者的

27、信息返回给对方。client在收到tracker的响应后,就能获取其它下载者的信息,那么它就可以根据这些信息,与其它下载者建立连接,从它们那里下载文件片断。2.1.6 bittorrent协议的发展最新的dht网络技术,使得无tracker下载成为可能。dht(distributed hash table,分布式哈希表)类似tracker的根据种子特征码返回种子信息的网络。dht全称叫分布式哈希表(distributed hash table),是一种分布式存储方法。在不需要服务器的情况下,每个客户端负责一个小范围的路由,并负责存储一小部分数据,从而实现整个dht网络的寻址和存储。新版bitc

28、omet允许同行连接dht网络和tracker,也就是说在完全不连上tracker服务器的情况下,也可以很好的下载,因为它可以在dht网络中寻找下载同一文件的其他用户。有些软件(比特精灵)还会自动通过dht搜索种子资源,构成种子市场。这种技术好处十分明显,就是大大减轻了tracker的负担。用户之间可以更快速建立通讯。对越每一个连入dht网络的计算机就称为一个网络节点,每一个节点,都会得到一个独一无二的id,相当于dht网络的身份表示,当然这个id的计算方法有很多种方法,所以就有各种各样的dht的实现方式,其中最自然的一种方法就是用他公网上的ip来做id的计算原形,因为每个主机的ip地址这是独

29、一无二的也是个唯一标示,当然一个计算机也可能有多个网卡,在dht网络中每一个节点保存了带下载的一部分的资源那么,整个dht的网络就是一个大的容器,里面存放了一定的资料,即整个dht网络保存着待下载软件的所有内容,对于网络中的节点资源是共享的,但由于数据在各个节点上是分散的,每个节点上的资源还会变化,所以问题来了,如何找到特定的资源存在于某个节点上,好去索取。在此之前,曾经有许多的方法,来解决这个,问题比如最早的napster,就是一个巨大的集中式索引服务器,里面存放了所有的资源的位置,这是一个很直观的解决方案,通过索引来查找资源,但是简单的方法虽然有效,也很脆弱,比如他的服务器万一挂掉了,整个

30、napster网络就完蛋了,而且,所有的资源在一起,整个服务器的负担随着资源的增多而越来越多,最后臃肿不堪,所以后来就出现了另一种解决方案,叫做全分布式非结构化网络,走了另一个极端,完全不要中心服务器,每一个节点维护一个邻居列表,类似路由器中路由表,告诉你下载的资源到哪去找,这样如果要找一个东西就问邻居,邻居再问邻居,只要有,总有一天被问到答案,这就是泛洪式搜索,的确在网络路由上掀起了一片数据洪水,最有名的就是gnutella协议,当初我在分析shareaza的时候就遇到这个协议了,当时一头雾水,现在看来这个协议还被做为bt协议的一个补充在被使用着.还有一种解决方案就是综合上述两者的优点,设置

31、一些超级节点,这些节点就好象napster上的中心服务器,里面存放了大量的索引信息,这就叫做半分布式结构,现在流行的bt就是这种技术,混血的就是强大。我这里讲的dht却是一个完全分布式结构化拓扑网络,是一个完全不需要中心服务器的网络拓扑,然而比非结构化的要有更好的搜索机制,不用泛洪,目前没有bt应用的那么广,不过大家应该注意到了bt和电骡都先后加入了dht网络,说明这个网络还是很有潜力的,作为bt或者电骡协议的一种补充手段,让你下载的时候,能够找到更多的源,提升了性能,而且完全不需要中心服务器,也是他的一个优点,这个网络有这样的功能,因为他是凝聚了一定的智慧的,不是象上面的那些都是很直观的解决

32、方案,所以他们都不够强大dht利用了一个小聪明,把节点的id给利用了起来,简单的说,就是把要找的资源,通过hash算法得到一个规范的key,把这个key和资源合在一起,就是一个信息,把这个信息放在和key一样或者"距离"最近的那个id节点上,这样你知道自己要找什么,用hash算法得到key,然后就在dht网络里发布搜索信息,指明要和key一样的id的节点,由于每一个节点都维护了一个其他节点的表,所以很快就能找到所要的东西,研究表明,找到所花费的寻址路径长度和每个节点所保存的邻居节点的个数有渐进曲线关系,所以只要说到这一层dht的奥秘就一目了然了。2.2 bittorrent

33、的软件要求2.2.1 软件系统设计要求设计一款功能齐备的bittorrent下载软件,具体要求如下:(1)能够实现对.torrent文件的解析并且显示出来(2)实现对任务的添加,开始,暂停,删除(3)实现多任务多线程下载(4)实现对种子文件的管理2.2.2 软件系统实现软件开发方法:采用面向对象技术开发方法开发语言:c+开发集成环境:qt creator使用c+作为开发语言,qt作为ide,对bittorrent下载过程进行抽象出具体的类。比如任务,种子,tracker等等。3 需求分析3.1 种子文件解析功能分析3.2 tracker服务器功能分析tracker服务器是bt下载中必须的角色。

34、一个bt client 在下载开始以及下载进行的过程中,要不停的与 tracker 服务器进行通信,以报告自己的信息,并获取其它下载client的信息。这种通信是通过 http 协议进行的,又被称为 tracker http 协议,它的过程是这样的: client 向 tracker 发一个http 的get请求,并把它自己的信息放在get的参数中;这个请求的大致意思是:我是xxx,我想下载yyy文件,我的ip是aaa,我用的端口是bbb。 tracker 对所有下载者的信息进行维护,当它收到一个请求后,首先把对方的信息记录下来(如果已经记录在案,那么就检查是否需要更新),然后将一部分(并非全

35、部,根据设置的参数已经下载者的请求)参与下载同一个文件(一个tracker服务器可能同时维护多个文件的下载)的下载者的信息返回给对方。 client在收到tracker的响应后,就能获取其它下载者的信息,那么它就可以根据这些信息,与其它下载者建立连接,从它们那里下载文件片断。3.3 torrent服务器功能分析torrent服务器是也是bt下载中必须的角色。torrent服务器也就一个peer服务器,当peer服务器从tracker服务器拿到peer列表名单的时候,开始和其他peer服务器创建连接,并且不断和彼此进行通信和交换。它的过程是这样的: torrent服务器向另一个torrent服务

36、器发送消息,这个消息的大致意思是:我是xxx,我已经下载过yyy文件或片段,你可以从我这里直接下载。然后另一个torrent服务器也向发送消息,大致意思是:我这里也有下载一些片段,你看看哪些片段你没下载过,你可以下载。3.4 软件需求分析通过可行性研究报告通过不同的角度判断软件的开发可行性,在确定软件开发可行的情况下,我们需要对软件需要实现的各个功能进行详细分析。对于软件开发周期中,需求分析阶段是一个很重要的阶段,因为连需求不明确,怎么才能开发出符合客户需求的软件,在这一阶段做得好,将为整个软件开发项目的成功打下良好的基础。我们必须明确我们要做什么。我们要实现这几个模块:种子的解析,连接模块,

37、peer管理,出错管理,任务界面管理。4 概要设计4.1.1 种子解析模块1 对种子文件进行解析,获得traceker服务器的地址,待下载文件的文件名和长度,piece长度和各个piece的hash值。2 实现对种子文件中下载多个文件的解析。4.1.2 连接模块1 连接traceker,根据http协议构造获取peer地址的请求,与traceker建立连接,解析traceker的响应信息,从而获取各个peer的ip地址和端口号。4.1.3 peer管理模块1 对下载下来的数据进行hash校验,判断是否已经下载过该piece。2 根据peer的ip地址和端口号连接peer,从peer处下载数据并

38、且将已经下载的数据上传给其他用户。4.1.4 出错处理模块1 出错处理,在软件使用的过程中可能出现各种意想不到大错误,所有要定义整个系统可能出现的错误类型,并且对错误进行相应的提示或捕获处理。4.1.5 窗口界面模块1 本软件的窗口包括一个带有菜单栏,工具栏和状态栏的主窗口,主窗口又分为任务树和任务列表两个视图。用户可以通过任务树或者任务表对结点进行添加,删除等操作,也可以对任务进行分类,实现对资源的管理。 图4-1 任务树图图4-2 任务表图5 详细设计5.1 系统功能模块本软件的模块大致如下。客户端主要包括:种子解析,连接管理,片段管理,出错管理,窗口管理。peer之间peer通信主要是通

39、过tracker服务器来确定和谁通信,而tracker服务对peer的下载信息进行维护。图5-1 系统功能图图5-2 bittorrent工作原理5.2 qt的信号与槽机制qt 是一个跨平台的 c+ gui 应用构架,它提供了丰富的窗口部件集,具有面向对象、易于扩展、真正的组件编程等特点,更为引人注目的是目前 linux 上最为流行的 kde 桌面环境就是建立在 qt 库的基础之上。qt 支持下列平台:ms/windows-95、98、nt 和 2000;unix/x11-linux、sun solaris、hp-ux、digital unix、ibm aix、sgi irix;embedde

40、d- 支持 framebuffer 的 linux 平台。伴随着 kde 的快速发展和普及,qt 很可能成为 linux 窗口平台上进行软件开发时的 gui 首选。信号和槽机制是 qt 的核心机制,要精通 qt 编程就必须对信号和槽有所了解。信号和槽是一种高级接口,应用于对象之间的通信,它是 qt 的核心特性,也是 qt 区别于其它工具包的重要地方。信号和槽是 qt 自行定义的一种通信机制,它独立于标准的 c/c+ 语言,因此要正确的处理信号和槽,必须借助一个称为 moc(meta object compiler)的 qt 工具,该工具是一个 c+ 预处理程序,它为高层次的事件处理自动生成所需

41、要的附加代码。在我们所熟知的很多 gui 工具包中,窗口小部件 (widget) 都有一个回调函数用于响应它们能触发的每个动作,这个回调函数通常是一个指向某个函数的指针。但是,在 qt 中信号和槽取代了这些凌乱的函数指针,使得我们编写这些通信程序更为简洁明了。 信号和槽能携带任意数量和任意类型的参数,他们是类型完全安全的,不会像回调函数那样产生 core dumps。所有从 qobject 或其子类 ( 例如 qwidget) 派生的类都能够包含信号和槽。当对象改变其状态时,信号就由该对象发射 (emit) 出去,这就是对象所要做的全部事情,它不知道另一端是谁在接收这个信号。这就是真正的信息封

42、装,它确保对象被当作一个真正的软件组件来使用。槽用于接收信号,但它们是普通的对象成员函数。一个槽并不知道是否有任何信号与自己相连接。而且,对象并不了解具体的通信机制。你可以将很多信号与单个的槽进行连接,也可以将单个的信号与很多的槽进行连接,甚至于将一个信号与另外一个信号相连接也是可能的,这时无论第一个信号什么时候发射系统都将立刻发射第二个信号。总之,信号与槽构造了一个强大的部件编程机制。信号与槽的定义槽:用来接收信号,可以被看作是普通成员函数,可以被直接调用。支持public,protected,private修饰,用来定义可以调用连接到此槽的范围。public slots:void test

43、slot(const qstring& strseqid); 信号:只需要声明信号名与参数列表即可,像是一个只有声明没有实现的成员函数。 signals:void testsignal(const qstring&); qt会在moc的cpp文件中实现它。下面代码中调用activate的第三个参数是类中信号的序列号。void ctestobject: testsignal (const qstring & _t1)void *_a = 0, const_cast<void*>(reinterpret_cast<const void*>(&

44、_t1) ;qmetaobject:activate(this, &staticmetaobject, 0, _a); 信号槽的连接与触发通过调用connect()函数建立连接,会把连接信息保存在sender对象中;调用desconnect()函数来取消。connect函数的最后一个参数来用指定连接类型。static bool connect(const qobject *sender, const qmetamethod &signal,const qobject *receiver, const qmetamethod &method, qt:connectiont

45、ype type = qt:autoconnection); 一切就绪,发射!在sender对象中调用:emit testsignal(“test”); # define emit 上面代码可以看到emit被定义为空,这样在发射信号时就相当于直接调用qt为我们moc出来的函数testsignal(constqstring & _t1)。具体的操作由qmetaobject:activate()来处理:遍历所有receiver并触发它们的slots。针对不同的连接类型,这里的派发逻辑会有不同。不同的连接类型剖析queuedconnection:向receiver所在线程的消息循环发送事件,

46、此事件得到处理时会调用slot,像win32的:postmessage。blockingqueuedconnection:处理方式和queuedconnection相同,但发送信号的线程会等待信号处理结束再继续,像win32的:sendmessage。directconnection:在当前线程直接调用receiver的slot,这种类型无法支持跨线程的通信。autoconnection:当前线程与receiver线程相同时,直接调用slot,否则同queuedconnection类型。 qobject * const receiver = c->receiver; / determin

47、e if this connection should be sent immediately or / put into the event queue if (c->connectiontype = qt:autoconnection && !receiverinsamethread) | (c->connectiontype = qt:queuedconnection) queued_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv); continue; #ifndef q

48、t_no_thread . else if (c->connectiontype = qt:blockingqueuedconnection) locker.unlock(); if (receiverinsamethread) qwarning("qt: dead lock detected while activating a blockingqueuedconnection: " "sender is %s(%p), receiver is %s(%p)", sender->metaobject()->classname(), s

49、ender, receiver->metaobject()->classname(), receiver); qsemaphore semaphore; qcoreapplication:postevent(receiver,new qmetacallevent(c->method_offset, c->method_relative, c->callfunction, sender, signal_absolute_index, 0, 0, argv ? argv : empty_argv, &semaphore); semaphore.acquire(

50、); locker.relock(); continue; #endif qt对象所属线程的概念这里要引入qobject的所属线程概念,看一下qobject的构造函数(随便选择一个重载)就一目了然了。如果指定父对象并且父对象的当前线程数据有效,则继承,否则把创建qobject的线程作为所属线程。 qobject:qobject(qobject *parent) : d_ptr(new qobjectprivate) q_d(qobject); d_ptr->q_ptr = this; d->threaddata=(parent&&!parent->thread

51、()? parent->d_func()->threaddata : qthreaddata:current(); d->threaddata->ref(); if (parent) qt_try if(!check_parent_thread(parent,parent? parent->d_func()->threaddata : 0, d->threaddata) parent = 0; setparent(parent); qt_catch(.) d->threaddata->deref(); qt_rethrow; qt_addo

52、bject(this); 通过activate()的代码可以看到,除了信号触发线程与接收者线程相同的情况能直接调用到slot,其它情况都依赖事件机制,也就是说receiver线程必须要有qt的eventloop,否则slot函数是没有机会触发的!当我们奇怪为什么信号发出slot却不被触发时,可以检查一下是否涉及到跨线程,接收者的线程是否存在激活的eventloop。所幸,我们可以通过调用qobject的方法movetothread,来更换对象的所属线程,将有需求接收信号的对象转移到拥有消息循环的线程中去以确保slot能正常工作。 有一个和对象所属线程相关的坑:qobject:deletelat

53、er() 。从源码可以看出,这个调用也只是发送了一个事件,等对象所属线程的消息循环获取控制权来处理这个事件时做真正的delete操作。所以调用这个方法要谨慎,确保对象所属线程具有激活的eventloop,不然这个对象就被泄露了!void qobject:deletelater() qcoreapplication:postevent(this, new qevent(qevent:deferreddelete); 强制线程切换当对象中的一些接口需要确保在具有消息循环的线程中才能正确工作时,可以在接口处进行线程切换,这样无论调用者在什么线程都不会影响对象内部的操作。下面的类就是利用信号槽机制来实

54、现线程切换与同步,所有对testmethod()的调用都会保证执行在具有事件循环的线程中。 class ctestobject : public qobject q_object public: ctestobject(qobject *parent = null) : qobject(parent) / 把自己转移到带有事件循环的qthread this->movetothread(&m_workthread); / 外部调用一律通过信号槽转移到对象内部的工作线程 / 连接类型选择为qt:blockingqueuedconnection来达到同步调用的效果 。 connect(

55、this, signal(signaltestmethod(const qstring &), this, slot(slottestmethod(const qstring &), qt:blockingqueuedconnection); m_workthread.start(); ctestobject(); void testmethod(const qstring& strarg) if(qthread:currentthreadid()=this->d_func()->threaddata->threadid) / 如果调用已经来自对象所属线程,直接处理 slottestmethod(strarg); else / 通过发送信号,实现切换线程处理 emit signaltestmethod(strarg); signals: void signaltestmethod(const qstring&); private slots: void slottestmethod(const qstring& strarg) / 方法的具体实现 private: qthread m_workthread;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论