版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
上海复旦大学毕业设计(论文)用纸绪论国内外BitTorrent的发展状况说到BitTorrent可能有人还不知道是什么东西,但是说到种子可谓是无人不知无人不晓啊!那么在这个下载过程是通过什么支撑的,或者说下载客户端与服务器之间是怎么预定通信的呢,那就是BitTorrent协议,用来进行对种子文件管理和规范。BitTorrent协议是一个网络文件传输协议,它能够实现点对点文件分享的技术。比起其他点对点的协议,它更有多点对多点的特性,这个特点简单的说就是:下载的人越多,速度越快。下载完不马上关闭BitTorrent软件,就可以成为种子即拥有完整的档案者分流让其他人下载,或者说BitTorrent一种分发文件的协议。它通过URL来识别内容,并且可以无缝的和web进行交互。它基于HTTP协议,它的优势是:如果有多个下载者并发的下载同一个文件,那么,每个下载者也同时为其它下载者上传文件,这样,文件源可以支持大量的用户进行下载,而只带来适当的负载的增长。发展BitTorrent的目的和意义发展BitTorrent的目的BitTorrent是一种P2P模式,对于P2P模式相对C/S模式,具有很多优点,但是随着P2P应用的不断增多,P2P技术也开始面临一些问题,例如路由效率低下、维护开销过大、系统稳定性差、安全性无法保证以及服务不可靠等问题。因此,在提高现有P2P网络资源定位的效率,降低其维护开销,增强P2P系统的稳定与安全性,提高P2P各个节点提供服务的可靠性等方面都需要做深入的研究。深入研究P2P资源定位技术有重要的理论和现实意义。一方面,随着P2P应用的不断增长,P2P资源定位技术遇到的一系列问题迫切需要我们对它进行更加深入的研究,这将有助于它的进一步推广和使用;另一方面,把P2P资源定位技术与其它的技术相结合,可以达到相互促进的效果,如把P2P资源定位技术引入到通讯领域,把P2P资源定位技术与网格技术相结合,都可以促进彼此的发展。发展BitTorrent的意义发展BitTorrent的意义对于大多数网民是不言而喻的。在平时的生活或学习大多数下载是下载一些音乐,电影和一些软件,尤其是电影,现在是已经进入了高清时代,一部高清电影动辄几个G,在中国的平均网速相对发达国家相对较低的情况下,在以前没有BT技术前,要下载高清电影简直是想都不敢想,占有很高的带宽,文件大,下载时间延长,势必会影响其他工作,而有了BT的迅速发展,通过互联网用户下载这个影片的数量大大加增,下载用户越多,速度越快!甚至有些公司提供离线下载服务,公司通过强大的服务器先通过BitTorrent协议把文件先下载到公司服务器,然后用户再从服务器取回到本地,可靠且速度快。Bitorrent技术广泛应用与电视直播,网络视频和在线游戏中。很多网络游戏的在线更新,比如说如魔兽世界就是采用BT的技术,所以当每次有改版时,动辄数百MB的更新包,通过游戏厂商所提供的更新程序,以BitTorrent协议的方式进行下载分流。这为以往的其他种在线游戏,每次重大改版就必须重新压制光盘,或是等待单一下载点的下载方式,带来另一种节省成本的经营模式。BitTorrent的原理分析综述BitTorrent的相关技术BitTorrent协议对于普通的HTTP/FTP下载使用TCP/IP协议,BitTorrent协议是架构于TCP/IP协议之上的一个P2P文件传输协议,处于TCP/IP结构的应用层。BitTorrent协议本身也包含了很多具体的内容协议和扩展协议,并在不断扩充中。根据BitTorrent协议,文件发布者会根据要发布的文件生成提供一个.torrent文件,即种子文件,也简称为“种子”,可以通过一些种子软件进行种子文件生成。种子文件本质上是文本文件,文本的内容包含Tracker信息和文件信息两部分。Tracker信息主要是BT下载中需要用到的Tracker服务器的地址和针对Tracker服务器的设置,也就是下载软件通过解析种子文件,通过Tracker信息然后和Tracker建立连接,进行通信,从服务器获取到Peer的列表,即你从其他客户端下载文件时建立连接需要的信息,同时也把你的主机的信息上传到Tracker供其他客户端下载。文件信息是根据对目标文件的计算生成的,即根据BitTorrent协议内的Bencode规则进行提供下载文件进行编码。主要是把提供下载的文件虚拟分成大小相等的块,块大小必须为2k的整数次方,由于是虚拟分块,硬盘上并不产生各个块文件,并把每个块的索引信息和Hash验证码写入种子文件中,确保块不被重复下载所以,种子文件就是被下载文件的“索引”。下载时,BT客户端首先解析种子文件得到Tracker地址,然后连接Tracker服务器。Tracker服务器回应下载者的请求,提供下载者其他下载者包括发布者的IP。下载者再连接其他下载者,根据种子文件,两者分别告知对方自己已经有的块,然后交换对方所没有的数据。此时不需要其他服务器参与,分散了单个线路上的数据流量,因此减轻了服务器负担。下载者每得到一个块,需要算出下载块的Hash验证码与种子文件中的对比,如果一样则说明块正确,不一样则需要重新下载这个块。这种规定是为了解决下载内容准确性的问题。一般的HTTP/FTP下载,发布文件仅在某个或某几个服务器,下载的人太多,服务器的带宽很易不胜负荷,变得很慢。而BitTorrent协议下载的特点是,下载的人越多,提供的带宽也越多,下载速度就越快。同时,拥有完整文件的用户也会越来越多,使文件的“寿命”不断延长。为了解决某些用户“下完就跑”的现象,在非官方BitTorrent协议中还存在一种慢慢开放下载内容的超级种子的算法。BitTorrent的专业术语Tracker:收集下载者信息的服务器,并将此信息提供给其他下载者,使下载者们相互连接起来,传输数据。种子:指一个下载任务中所有文件都被某下载者完整的下载,此时下载者成为一个种子。发布者本身发布的文件就是原始种子。也指.torrent文件。做种:发布者提供下载任务的全部内容的行为;下载者下载完成后继续提供给他人下载的行为。种子的解析如图所示为种子文件内容。图2-1BT种子文件结构图BT种子文件使用了一种叫bencoding的编码方法来保存数据。bencoding现有四种类型的数据:strings(字符串),integers(整数),lists(列表),dictionaries(字典)(1)strings(字符串)编码为:<字符串长度>:<字符串>例如:4:test表示为字符串"test",表示长度为4个字节的字符串testStrings类型是没有没开始或结束标记(2)integers(整数)编码为:i<整数>e开始标记i,结束标记为e例如:i1234e表示为整数1234i-1234e表示为整数-1234整数没有大小限制(3)lists(列表)编码为:l<bencoding编码类型>e开始标记为l,结束标记为e列表里可以包含任何bencoding编码类型,包括整数,字符串,列表,字典。例如:l4:test5:abcdee表示为二个字符串["test","abcde"](4)dictionaries(字典)编码为d<bencoding字符串><bencoding编码类型>e开始标记为d,结束标记为e关键字必须为bencoding字符串值可以为任何bencoding编码类型例如:d3:agei20ee表示为{"age"=20}d4:path3:C:"8:filename8:test.txt表示为{"path"="C:"","filename"="test.txt"}(5)具体文件结构如下:全部内容必须都为bencoding编码类型。整个文件为一个字典结构,包含如下关键字announce:tracker服务器的URL(字符串)announce-list(可选):备用tracker服务器列表(列表)creationdate(可选):种子创建的时间,Unix标准时间comment(可选):备注(字符串)createdby(可选):创建人或创建程序的信息(字符串)info:一个字典结构,包含文件的主要信息,分为单文件结构或多文件结构。单文件结构:length:文件长度,单位字节(整数)md5sum(可选):长32个字符的文件的MD5校验(字符串)name:文件名(字符串)piecelength:每个块的大小,单位字节(整数)pieces:每个块的20个字节的SHA1Hash的值(二进制格式)多文件结构如下:files:一个字典结构length:文件长度,单位字节(整数)md5sum(可选):同单文件结构中相同path:文件的路径和名字,是一个列表结构name:最上层的目录名字(字符串)piecelength:同单文件结构中相同pieces:同单文件结构中相同综上,多文件Torrent的结构的树形图。图2-2多文件结构图图2-3单文件结构图BitTorrent运行原理BT原理普通的HTTP/FTP下载使用TCP/IP协议,BitTorrent协议是架构于TCP/IP协议之上的一个P2P文件传输协议,处于TCP/IP结构的应用层。BitTorrent协议本身也包含了很多具体的内容协议和扩展协议,并在不断扩充中。
根据BitTorrent协议,文件发布者会根据要发布的文件生成提供一个.torrent文件,即种子文件,也简称为“种子”。
torrent文件本质上是文本文件,包含Tracker信息和文件信息两部分。Tracker信息主要是BT下载中需要用到的Tracker服务器的地址和针对Tracker服务器的设置,文件信息是根据对目标文件的计算生成的,计算结果根据BitTorrent协议内的B编码规则进行编码。它的主要原理是需要把提供下载的文件虚拟分成大小相等的块,块大小必须为2k的整数次方,由于是虚拟分块,硬盘上并不产生各个块文件,并把每个块的索引信息和Hash验证码写入.torrent文件中;所以,种子文件就是被下载文件的“索引”。
下载者要下载文件内容,需要先得到相应的.torrent文件,然后使用BT客户端软件进行下载。
下载时,BT客户端首先解析.torrent文件得到Tracker地址,然后连接Tracker服务器。Tracker服务器回应下载者的请求,提供下载者其他下载者(包括发布者)的IP。下载者再连接其他下载者,根据.torrent文件,两者分别对方告知自己已经有的块,然后交换对方没有的数据。此时不需要其他扮演服务器参与,分散了单个线路上的数据流量,因此减轻了服务器负担。
下载者每得到一个块,需要算出下载块的Hash验证码与.torrent文件中的对比,如果一样则说明块正确,不一样则需要重新下载这个块。这种规定是为了解决下载内容准确性的问题。
一般的HTTP/FTP下载,发布文件仅在某个或某几个服务器,下载的人太多,服务器的带宽很易不胜负荷,变得很慢。而BitTorrent协议下载的特点是,下载的人越多,提供的带宽也越多,种子也会越来越多,下载速度就越快。
而有些人下载完成后关掉下载任务,提供较少量数据给其他用户,为尽量避免这种行为,在非官方BitTorrent协议中存在超级种子的算法。这种算法允许文件发布者分几步发布文件,发布者不需要一次提供文件所有内容,而是慢慢开放的下载内容的比例,延长下载时间。此时,速度快的人由于未下载完必须提供给他人数据,速度慢的人有更多机会得到数据。BitTorrent下载流程在整个下载过程,tracker服务器一个不可缺少的角色,它不同的下载者之间搭了一个桥梁,下载者在下载开始以及下载进行的过程中,要不停的与tracker服务器进行通信,以汇报自己的信息,并获取其它下载client的信息。这种通信是通过HTTP协议进行的,又被称为trackerHTTP协议,它的过程是这样的:client向tracker发一个HTTP的GET请求,并把它自己的信息放在GET的参数中;这个请求的大致意思是:我是xxx,我想下载yyy文件,我的ip是aaa,我用的端口是bbb。tracker对所有下载者的信息进行维护,当它收到一个请求后,首先把对方的信息记录下来,如果已经记录在案,那么就检查是否需要更新,然后将一部分,并非全部,根据设置的参数已经下载者的请求参与下载同一个文件,一个tracker服务器可能同时维护多个文件的下载,的下载者的信息返回给对方。Client在收到tracker的响应后,就能获取其它下载者的信息,那么它就可以根据这些信息,与其它下载者建立连接,从它们那里下载文件片断。BitTorrent协议的发展最新的DHT网络技术,使得无Tracker下载成为可能。DHT(DistributedHashTable,分布式哈希表)类似Tracker的根据种子特征码返回种子信息的网络。DHT全称叫分布式哈希表(DistributedHashTable),是一种分布式存储方法。在不需要服务器的情况下,每个客户端负责一个小范围的路由,并负责存储一小部分数据,从而实现整个DHT网络的寻址和存储。新版BitComet允许同行连接DHT网络和Tracker,也就是说在完全不连上Tracker服务器的情况下,也可以很好的下载,因为它可以在DHT网络中寻找下载同一文件的其他用户。有些软件(比特精灵)还会自动通过DHT搜索种子资源,构成种子市场。这种技术好处十分明显,就是大大减轻了Tracker的负担。用户之间可以更快速建立通讯。对越每一个连入DHT网络的计算机就称为一个网络节点,每一个节点,都会得到一个独一无二的ID,相当于DHT网络的身份表示,当然这个ID的计算方法有很多种方法,所以就有各种各样的DHT的实现方式,其中最自然的一种方法就是用他公网上的IP来做ID的计算原形,因为每个主机的IP地址这是独一无二的也是个唯一标示,当然一个计算机也可能有多个网卡,在DHT网络中每一个节点保存了带下载的一部分的资源那么,整个DHT的网络就是一个大的容器,里面存放了一定的资料,即整个DHT网络保存着待下载软件的所有内容,对于网络中的节点资源是共享的,但由于数据在各个节点上是分散的,每个节点上的资源还会变化,所以问题来了,如何找到特定的资源存在于某个节点上,好去索取。在此之前,曾经有许多的方法,来解决这个,问题比如最早的napster,就是一个巨大的集中式索引服务器,里面存放了所有的资源的位置,这是一个很直观的解决方案,通过索引来查找资源,但是简单的方法虽然有效,也很脆弱,比如他的服务器万一挂掉了,整个napster网络就完蛋了,而且,所有的资源在一起,整个服务器的负担随着资源的增多而越来越多,最后臃肿不堪,所以后来就出现了另一种解决方案,叫做全分布式非结构化网络,走了另一个极端,完全不要中心服务器,每一个节点维护一个邻居列表,类似路由器中路由表,告诉你下载的资源到哪去找,这样如果要找一个东西就问邻居,邻居再问邻居,只要有,总有一天被问到答案,这就是泛洪式搜索,的确在网络路由上掀起了一片数据洪水,最有名的就是Gnutella协议,当初我在分析shareaza的时候就遇到这个协议了,当时一头雾水,现在看来这个协议还被做为bt协议的一个补充在被使用着.还有一种解决方案就是综合上述两者的优点,设置一些超级节点,这些节点就好象napster上的中心服务器,里面存放了大量的索引信息,这就叫做半分布式结构,现在流行的bt就是这种技术,混血的就是强大。我这里讲的DHT却是一个完全分布式结构化拓扑网络,是一个完全不需要中心服务器的网络拓扑,然而比非结构化的要有更好的搜索机制,不用泛洪,目前没有BT应用的那么广,不过大家应该注意到了BT和电骡都先后加入了DHT网络,说明这个网络还是很有潜力的,作为BT或者电骡协议的一种补充手段,让你下载的时候,能够找到更多的源,提升了性能,而且完全不需要中心服务器,也是他的一个优点,这个网络有这样的功能,因为他是凝聚了一定的智慧的,不是象上面的那些都是很直观的解决方案,所以他们都不够强大DHT利用了一个小聪明,把节点的id给利用了起来,简单的说,就是把要找的资源,通过hash算法得到一个规范的key,把这个key和资源合在一起,就是一个信息,把这个信息放在和key一样或者"距离"最近的那个id节点上,这样你知道自己要找什么,用hash算法得到key,然后就在DHT网络里发布搜索信息,指明要和key一样的id的节点,由于每一个节点都维护了一个其他节点的表,所以很快就能找到所要的东西,研究表明,找到所花费的寻址路径长度和每个节点所保存的邻居节点的个数有渐进曲线关系,所以只要说到这一层DHT的奥秘就一目了然了。BitTorrent的软件要求软件系统设计要求设计一款功能齐备的BitTorrent下载软件,具体要求如下:(1)能够实现对.torrent文件的解析并且显示出来(2)实现对任务的添加,开始,暂停,删除(3)实现多任务多线程下载(4)实现对种子文件的管理软件系统实现软件开发方法:采用面向对象技术开发方法开发语言:C++开发集成环境:QTCreator使用c++作为开发语言,QT作为IDE,对BitTorrent下载过程进行抽象出具体的类。比如任务,种子,tracker等等。需求分析种子文件解析功能分析Tracker服务器功能分析tracker服务器是BT下载中必须的角色。一个BTclient在下载开始以及下载进行的过程中,要不停的与tracker服务器进行通信,以报告自己的信息,并获取其它下载client的信息。这种通信是通过HTTP协议进行的,又被称为trackerHTTP协议,它的过程是这样的:
client向tracker发一个HTTP的GET请求,并把它自己的信息放在GET的参数中;这个请求的大致意思是:我是xxx,我想下载yyy文件,我的ip是aaa,我用的端口是bbb。
tracker对所有下载者的信息进行维护,当它收到一个请求后,首先把对方的信息记录下来(如果已经记录在案,那么就检查是否需要更新),然后将一部分(并非全部,根据设置的参数已经下载者的请求)参与下载同一个文件(一个tracker服务器可能同时维护多个文件的下载)的下载者的信息返回给对方。
Client在收到tracker的响应后,就能获取其它下载者的信息,那么它就可以根据这些信息,与其它下载者建立连接,从它们那里下载文件片断。Torrent服务器功能分析torrent服务器是也是BT下载中必须的角色。Torrent服务器也就一个peer服务器,当peer服务器从tracker服务器拿到peer列表名单的时候,开始和其他peer服务器创建连接,并且不断和彼此进行通信和交换。它的过程是这样的:
torrent服务器向另一个torrent服务器发送消息,这个消息的大致意思是:我是xxx,我已经下载过yyy文件或片段,你可以从我这里直接下载。然后另一个torrent服务器也向发送消息,大致意思是:我这里也有下载一些片段,你看看哪些片段你没下载过,你可以下载。软件需求分析通过可行性研究报告通过不同的角度判断软件的开发可行性,在确定软件开发可行的情况下,我们需要对软件需要实现的各个功能进行详细分析。对于软件开发周期中,需求分析阶段是一个很重要的阶段,因为连需求不明确,怎么才能开发出符合客户需求的软件,在这一阶段做得好,将为整个软件开发项目的成功打下良好的基础。我们必须明确我们要做什么。我们要实现这几个模块:种子的解析,连接模块,Peer管理,出错管理,任务界面管理。概要设计种子解析模块对种子文件进行解析,获得Traceker服务器的地址,待下载文件的文件名和长度,piece长度和各个piece的hash值。实现对种子文件中下载多个文件的解析。连接模块连接Traceker,根据HTTP协议构造获取Peer地址的请求,与Traceker建立连接,解析Traceker的响应信息,从而获取各个peer的ip地址和端口号。Peer管理模块对下载下来的数据进行hash校验,判断是否已经下载过该piece。根据peer的IP地址和端口号连接peer,从peer处下载数据并且将已经下载的数据上传给其他用户。出错处理模块出错处理,在软件使用的过程中可能出现各种意想不到大错误,所有要定义整个系统可能出现的错误类型,并且对错误进行相应的提示或捕获处理。窗口界面模块本软件的窗口包括一个带有菜单栏,工具栏和状态栏的主窗口,主窗口又分为任务树和任务列表两个视图。用户可以通过任务树或者任务表对结点进行添加,删除等操作,也可以对任务进行分类,实现对资源的管理。图4-1任务树图图4-2任务表图详细设计系统功能模块本软件的模块大致如下。客户端主要包括:种子解析,连接管理,片段管理,出错管理,窗口管理。Peer之间peer通信主要是通过tracker服务器来确定和谁通信,而tracker服务对peer的下载信息进行维护。图5-1系统功能图图5-2BitTorrent工作原理QT的信号与槽机制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平台。伴随着KDE的快速发展和普及,QT很可能成为Linux窗口平台上进行软件开发时的GUI首选。信号和槽机制是QT的核心机制,要精通QT编程就必须对信号和槽有所了解。信号和槽是一种高级接口,应用于对象之间的通信,它是QT的核心特性,也是QT区别于其它工具包的重要地方。信号和槽是QT自行定义的一种通信机制,它独立于标准的C/C++语言,因此要正确的处理信号和槽,必须借助一个称为moc(MetaObjectCompiler)的QT工具,该工具是一个C++预处理程序,它为高层次的事件处理自动生成所需要的附加代码。在我们所熟知的很多GUI工具包中,窗口小部件(widget)都有一个回调函数用于响应它们能触发的每个动作,这个回调函数通常是一个指向某个函数的指针。但是,在QT中信号和槽取代了这些凌乱的函数指针,使得我们编写这些通信程序更为简洁明了。信号和槽能携带任意数量和任意类型的参数,他们是类型完全安全的,不会像回调函数那样产生coredumps。所有从QObject或其子类(例如Qwidget)派生的类都能够包含信号和槽。当对象改变其状态时,信号就由该对象发射(emit)出去,这就是对象所要做的全部事情,它不知道另一端是谁在接收这个信号。这就是真正的信息封装,它确保对象被当作一个真正的软件组件来使用。槽用于接收信号,但它们是普通的对象成员函数。一个槽并不知道是否有任何信号与自己相连接。而且,对象并不了解具体的通信机制。你可以将很多信号与单个的槽进行连接,也可以将单个的信号与很多的槽进行连接,甚至于将一个信号与另外一个信号相连接也是可能的,这时无论第一个信号什么时候发射系统都将立刻发射第二个信号。总之,信号与槽构造了一个强大的部件编程机制。信号与槽的定义槽:用来接收信号,可以被看作是普通成员函数,可以被直接调用。支持public,protected,private修饰,用来定义可以调用连接到此槽的范围。publicslots:voidtestslot(constQString&strSeqId);信号:只需要声明信号名与参数列表即可,像是一个只有声明没有实现的成员函数。Signals:voidtestsignal(constQString&);QT会在moc的cpp文件中实现它。下面代码中调用activate的第三个参数是类中信号的序列号。voidCTestObject::testsignal(constQString&_t1){void*_a[]={0,const_cast<void*>(reinterpret_cast<constvoid*>(&_t1))};QMetaObject::activate(this,&staticMetaObject,0,_a);}信号槽的连接与触发通过调用connect()函数建立连接,会把连接信息保存在sender对象中;调用desconnect()函数来取消。connect函数的最后一个参数来用指定连接类型。staticboolconnect(constQObject*sender,constQMetaMethod&signal,constQObject*receiver,constQMetaMethod&method,Qt::ConnectionTypetype=Qt::AutoConnection);一切就绪,发射!在sender对象中调用:emittestsignal(“test”);#defineemit上面代码可以看到emit被定义为空,这样在发射信号时就相当于直接调用QT为我们moc出来的函数testsignal(constQString&_t1)。具体的操作由QMetaObject::activate()来处理:遍历所有receiver并触发它们的slots。针对不同的连接类型,这里的派发逻辑会有不同。不同的连接类型剖析QueuedConnection:向receiver所在线程的消息循环发送事件,此事件得到处理时会调用slot,像Win32的::PostMessage。BlockingQueuedConnection:处理方式和QueuedConnection相同,但发送信号的线程会等待信号处理结束再继续,像Win32的::SendMessage。DirectConnection:在当前线程直接调用receiver的slot,这种类型无法支持跨线程的通信。AutoConnection:当前线程与receiver线程相同时,直接调用slot,否则同QueuedConnection类型。QObject*constreceiver=c->receiver;//determineifthisconnectionshouldbesentimmediatelyor//putintotheeventqueueif((c->connectionType==Qt::AutoConnection&&!receiverInSameThread)||(c->connectionType==Qt::QueuedConnection)){queued_activate(sender,signal_absolute_index,c,argv?argv:empty_argv);continue;#ifndefQT_NO_THREAD.}elseif(c->connectionType==Qt::BlockingQueuedConnection){locker.unlock();if(receiverInSameThread){qWarning("Qt:DeadlockdetectedwhileactivatingaBlockingQueuedConnection:""Senderis%s(%p),receiveris%s(%p)",sender->metaObject()->className(),sender,receiver->metaObject()->className(),receiver);}QSemaphoresemaphore;QCoreApplication::postEvent(receiver,newQMetaCallEvent(c->method_offset,c->method_relative,c->callFunction,sender,signal_absolute_index,0,0,argv?argv:empty_argv,&semaphore));semaphore.acquire();locker.relock();continue;#endif}QT对象所属线程的概念这里要引入QObject的所属线程概念,看一下QObject的构造函数(随便选择一个重载)就一目了然了。如果指定父对象并且父对象的当前线程数据有效,则继承,否则把创建QObject的线程作为所属线程。QObject::QObject(QObject*parent):d_ptr(newQObjectPrivate){Q_D(QObject);d_ptr->q_ptr=this;d->threadData=(parent&&!parent->thread())?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_addObject(this);}通过activate()的代码可以看到,除了信号触发线程与接收者线程相同的情况能直接调用到slot,其它情况都依赖事件机制,也就是说receiver线程必须要有QT的eventloop,否则slot函数是没有机会触发的!当我们奇怪为什么信号发出slot却不被触发时,可以检查一下是否涉及到跨线程,接收者的线程是否存在激活的eventloop。所幸,我们可以通过调用QObject的方法movetothread,来更换对象的所属线程,将有需求接收信号的对象转移到拥有消息循环的线程中去以确保slot能正常工作。有一个和对象所属线程相关的坑:QObject::deletelater()。从源码可以看出,这个调用也只是发送了一个事件,等对象所属线程的消息循环获取控制权来处理这个事件时做真正的delete操作。所以调用这个方法要谨慎,确保对象所属线程具有激活的eventloop,不然这个对象就被泄露了!voidQObject::deleteLater(){QCoreApplication::postEvent(this,newQEvent(QEvent::DeferredDelete));}强制线程切换当对象中的一些接口需要确保在具有消息循环的线程中才能正确工作时,可以在接口处进行线程切换,这样无论调用者在什么线程都不会影响对象内部的操作。下面的类就是利用信号槽机制来实现线程切换与同步,所有对testMethod()的调用都会保证执行在具有事件循环的线程中。classCTestObject:publicQObject{Q_OBJECTpublic:CTestObject(QObject*parent=NULL):QObject(parent){//把自己转移到带有事件循环的QThreadthis->moveToThread(&m_workThread);//外部调用一律通过信号槽转移到对象内部的工作线程//连接类型选择为Qt::BlockingQueuedConnection来达到同步调用的效果。connect(this,SIGNAL(signalTestMethod(constQString&)),this,SLOT(slotTestMethod(constQString&)),Qt::BlockingQueuedConnection);m_workThread.start();}~CTestObject();voidtestMethod(constQString&strArg){if(QThread::currentThreadId()==this->d_func()->threadData->threadId){//如果调用已经来自对象所属线程,直接处理slotTestMethod(strArg);}else{//通过发送信号,实现切换线程处理emitsignalTestMethod(strArg);}}signals:voidsignalTestMethod(constQString&);privateslots:voidslotTestMethod(constQString&strArg){//方法的具体实现}private:QThread m_workThread;};BT的算法与策略阻塞算法BT并不集中分配资源。每个peer自己有责任来尽可能的提高它的下载速率。Peers从它可以连接的peers处下载文件,并根据对方提供的下载速率给予同等的上传回报。对于合作者,提供上传服务,对于不合作的,就阻塞对方。所以说,阻塞是一种临时的拒绝上传策略,虽然上传停止了,但是下载仍然继续。在阻塞停止的时候,连接并不需要重新建立。每个客户端一直与固定数量的peer保持疏通,通常情况下是4个,严格地根据当前的下载速度来决定哪些peer应该保持疏通,通过计算最近10秒从每个peer处下载数据的速度来计算下载速度,如果只是简单地为提供最高下载速率的4个peer提供上载服务,那么就没有办法发现那些空闲的连接是否有更好的下载速度,为了解决这个问题,在任何时候,每个peer都拥有一个成为optimisticunchoking优化非阻塞,这个连接总是疏通状态,而不管它的下载速率是多少,每隔30秒,重新选择一个peer作为优化非阻塞的peer,一旦某一个peer完成了下载,它不能再通过下载速率来决定哪些peer提供上载了。目前采用的解决办法是:优先选择那些从它这里得到更好下载速率的peer,保持与它们的疏通,这样做的理由是尽可能的利用上载带宽,一旦某一个peer完成下载,那么它也就成为了种子。超级种子算法超级种子概念不是老版本BT协议的一部分。S5.5中的超级种子的概念是为帮助那些自身带宽有限(对支持大的Torrent来说)的发起者而设计的一种新的做种算法,它能使发起者减少需要上传的数据量以便spawnnewseedsinthetorrent。当一个做种的Client进入了超级种子模式,它的行为将不同于普通的做种者,而是扮成一个不拥有任何数据的普通Client。当其他的Client和它建立连接之后,它将通知这些Clients自己收到了一个从未被发送过的Piece(所有Piece都被发送过的情况是很罕见的),这就使得Clients只试图下载这一个Piece(而没有其他想法)。当Clients下载完这个Piece后,超级种子不再通知他们下载其他的Pieces直到它看到刚刚传送的那一个Piece已经被至少一个其他的Client提供下载。因此在那之前,Clients都不会访问超级种子的其他Pieces,这样就节省了超级种子的带宽。这种方法将提高做种的效率,既让Peers去下载最稀有的数据(降低了传送的多余数据量),又限制了传送给Peers的对Swarm没有任何贡献的数据量。这种算法未出现之前,一个种子在其他Client成为种子之前,可能需要上传150%~200%于Torrent的数据量。而现在,一个运行在超级种子模式下的Client(对一个大的Torrent做种),只需要上传105%于Torrent的数据量。这相当于一个普通种子做种效率的150%~200%。但是,在通常情况下不建议使用超级种子模式。虽然它有助于稀有数据的分发(因为它对Client的下载选择做出了限制,同时也限制了Clients下载已经部分得到的数据),所以超级种子模式只适用于那些最初做种的Server。结束算法当下载将要结束时,将会趋向最后的几个piece-sections下载减慢,为了加速下载,客户端向所有peers发送请求下载其没有的piece。为了保证传输过多的冗余数据而到是性能下降,客户端一旦收到piece-sections,向所有的其他peers发送cancel消息。至于什么时候启动END
GAME算法。规范没有给出推荐值。防冷落算法偶然情况下,BT的peer端可能会被它下载的所有的peers端阻塞。这种情况下,此peer端的下载速率就很低,直到优化unchock算法找到更好的peers端。为了消除这个问题,当超过一分钟一个peer没有从特定的peer得到一个piece那么BT就认为它被那个peer冷落。并不上传给它直到优化unchoke(这是对于上述的优化unchocke算法的一个例外),这就常常会使多于一个peers同时进入优化unchoke状态。从而使下载速率快速恢复。最佳无阻塞算法当同一时刻通过多个连接发送数据时,TCP拥塞控制的效果很差。这样,Choking就允许Peers使用一种tit-for-tat-ish算法来确保他们获得一个稳定的下载速率。下面介绍的Choking算法是目前BT客户端中所广泛采用的。很重要的一点是,所有新的算法既能用在包含他们全部的网络上,也能用在只包含此算法的网络上。好的Choking算法应该满足如下准则:1.为了获得好的TCP性能,它应限制同时上传的数量;2.应避免阻塞和非阻塞状态的频繁切换(Fibrillation);3.应该酬谢让自己下载的Peer,为它提供上载;4.当发现更好的连接(相对于当前的连接)的时候,试图启用他们,称作Optimistic
Unchoking。
目前使用的Choking算法中避免Fibrillation(抖动)的唯一策略是:每10秒更新被阻塞的Peers。酬谢(Reciprocation)和限制上传的数目通过解除(对自己感兴趣的且拥有最好的上载速率的)4个Peers的阻塞来管理。这样可以获得最大的下载速率。而这四个Peers因对己感兴趣而成为下载者。拥有更好的上载速率(相对于下载者而言)但对自己不感兴趣的Peer被阻塞,但一旦当它对自己感兴趣,则阻塞上载速率最慢的下载者,使其取而代之成为新的下载者。如果一个Client拥有完整的资源文件,则它将根据上载速率而不是下载速率来决定阻塞哪些Peer。对于Optimistic
Unchoked,在任意时刻都会有一个不被阻塞的Peer而不管它的上载速率如何(如果它对自己感兴趣,则成为4个下载者中的一员),至于哪一个Peer被Optimistic
Unchoked,会每30秒更新一次。最新连接的Peer成为Optimistic
Unchoked的可能性是其他Peers的3倍,这将给他们一个很好的机会去完成一个Piece的上载。最稀有算法BT中下载piece策略为,最稀少最优先原则。每个peer都优先选择整个系统中最少的那些片断去下载,而那些在系统中相对较多的片断,放在后面下载,这样,整个系统就趋向于一种更优的状态。如果不用这种算法,大家都去下载最多的那些片断,那么这些片断就会在系统中分布的越来越多,而那些在系统中相对较少的片断仍然很少,最后,某些
peer
就不再拥有其它
peer
感兴趣的片断了,那么系统的参与者越来越少,整个系统的性能就下降。客户端通过保留每个peer端的原始bitfield域来决定下载在bitfield里面出现频率最小的piece。程序的具体实现是通过
have
消息来计算。在下载过程中,会不停的收到其它
peer
发来的
have
消息,每个have消息都表明对方拥有了某个片断(即某个完整的piece)。那么,为每个片断维护一个计数器,每收到一个have消息,相应的计数器加1。在选择片断的时候,计数器最小的某个片断被选中。
“最少优先”的一个例外是在下载刚开始的时候。此时,下载者没有任何片断可供上传,所以,需要尽快的获取一个完整的片断。而最少的片断,通常只有某一个peer拥有,所以,它可能比多个peers都拥有的那些片断下载的要慢。因此,第一个片断是随机选择的,直到第一个片断下载完成,才切换到“最少优先”的策略。BT软件的模块的实现种子解析模块的实现根据种子文件的结构信息,我门可以构造文件的实体类,种子文件也可以被称为元信息文件,它是通过B编码,就是一个B编码的字典。因为在下载的文件可能是单个文件也有可能是多个文件,所以定义一个单文件结构体MetaInfoSingleFile,包含有长度,md5,名字,还有piece的长度等属性,然后再定义一个结构体为多文件结构体MetaInfoMultiFile。对于种子文件我们相应的定义一个MetaInfo,这个类保存种子的信息。.torrent说白就是个文本文件,对这文本文件读取保存到一个字节数组里面,MetaInfo通过调用parse(QByteArray)方法对字节数组进行解析,之后种子的所有信息就保存到一个MetaInfo对象中。Client与Traceker通信模块的实现解析完种子文件以后,种子的所有信息保存在实体类里面,可以通过类里面的一些方法获取种子的信息,完成种子的解析后,可以从中获取到Tracker服务器的URI后就可以开始和Tracker进行交互,在与traceker连接之后,tracker可以对一些自己下载进度进行统计,并且客户端可以获取到当前下载同一文件的peer的IP地址和端口号。BitTorrent协议是在TCP/IP协议之上的应用层协议,客户端使用HTTP协议与Tracker进行通信,Tracker通过HttpGET方法获取请求,然后Tracker服务器返回信息,返回信息是一个经过B编码的字典,包含着可以下载的peer的IP地址和端口号,和一些peer的长度等信息,然后客户端可以根据返回信息进行连接下载peer,并且在客户端下载完成peer以后,把相应的信息提交daotracker服务器,其他客户端可以根据Tracker服务器上面的信息得到你的ip地址和端口号,别人和你建立连接以后就可以下载你已经下载好的Peer.在这个软件开发过程中抽象出一个类TrackerClient,这个类主要和traceker服务器进行通信,包括请求和获取。Peer之间的通信模块的实现Peer之间通信协议可以称为peer连线协议,它是一个基于TCP协议的应用层协议,为防止有的peer只下载不上传,BT协议建议:客户端只给那些向它提供最快下载速度的4个Peer上传数据,简单地说就是谁向我提供下载,我就提供数据供他下载;谁不提供数据给我下载,我的数据也不会上传给它。客户端每隔一定时间,重新计算从各个peer处下载数据的速度,将下载速度最快的4个peer解除阻塞,允许这4个peer从客户端下载数据,同时将其他peer阻塞。对客户端与其他peer建立连接之后,既要做服务器又要做客户端,所以相应的有个作为客户端的类和作为服务器的类,一个负责从别的peer下载片段并且保存,一个负责上传本地已经下载好的片段。软件出错模块的实现在整个软件系统中定义5中错误状态,并且对这五种错误进行了相应的处理有UnknownError,TorrentParseError,InvalidTrackerError,FileErrorServerError在打开种子文件,和文件解析过程中或通信过程可能出现不同错误,要对不同的错误进行捕获,并且进行处理。下载任务状态的实现对于整个软件来说,添加一个种子文件,即为创建一个任务,任务的状态分为:Idle,Paused,Stopping,Preparing,Searching,Connecting,WarmingUp,Downloading,EndGame,Seeding.在peer与peer通信过程中或client与traceker服务器通信过程中会影响任务的状态。软件主界面模块的实现主界面效果如图所示。图5-3BT软件下载任务效果图图5-3BT软件下载任务效果图图5-4BT软件添加任务图图5-4BT软件添加任务图代码实现添加种子代码如图所示。图5-5BT软件添加种子代码图图5-6BT软件种子添加代码图//添加TorrentboolMainWindow::addTorrent(){//选择torrent文件QStringfileName=QFileDialog::getOpenFileName(this,tr("请选择一个文件"),lastDirectory,tr("种子文件(*.torrent);;""所有文件(*.*)"));if(fileName.isEmpty())returnfalse;lastDirectory=QFileInfo(fileName).absolutePath();qDebug()<<lastDirectory<<endl;//显示添加种子文件对话框AddTorrentDialog*addTorrentDialog=newAddTorrentDialog(this);addTorrentDialog->setTorrent(fileName);addTorrentDialog->deleteLater();if(!addTorrentDialog->exec())returnfalse;//添加任务到列表中需要把种子文件的路径和保存路径作为参数传过去addTorrent(fileName,addTorrentDialog->getDestinationFolder());if(!saveChanges){saveChanges=true;QTimer::singleShot(1000,this,SLOT(saveSettings()));}returntrue;}解析种子代码MetaInfoSingleFile是相应的单文件结构体MetaInfoMultiFile是相应的多文件结构体MetaInfo是相应的种子文件的实体类structMetaInfoSingleFile{qint64length;QByteArraymd5sum;QStringname;intpieceLength;QList<QByteArray>sha1Sums;};structMetaInfoMultiFile{qint64length;QByteArraymd5sum;QStringpath;};classMetaInfo{public:enumFileForm{SingleFileForm,MultiFileForm};}这个主要就是用来解析种子文件,转换为MetaInfoboolMetaInfo::parse(constQByteArray&data){//传过来的就是个文件流,然后文件进行bencoding编码解析即可returntrue;}Peer通信代码trackerclient.cpp主要是负责软件与Tracker的通信,用来负责获取peer列表和提交自己的进度就是用来获取peer列表voidTrackerClient::fetchPeerList(){从种子文件获取Tracker的url对本地的片段进行hash算法,向服务提交本地的下载信息发送Http请求}torrentclient.cpp主要是本机作为客户端,从其他Peer下载片段本机连接到Peer,从peer获取数据voidTorrentClient::connectToPeers(){//根据获取的peer列表的信息,连接主机,建立连接//启动一个通信线程处理数据交换}torrentserver.cpp主要是本机作为服务端,为其他Peer提供下载这个函数主要负责其他Peer请求连接,然后建立连接voidTorrentServer::incomingConnection(qintptrsocketDescriptor)窗体中任务代码如图所示。图5-7主窗体代码图mytablewidget.cpp主要负责对表格视图中任务的更删改查//添加任务行voidaddTaskRow(QStringname,QStringsize);//删除选择任务行voiddeleteTaskRow(intindex);//删除选择所有行voiddeleteAllTaskRow();mytreewidget.cpp主要负责对树视图中任务的更删改查//向树添加节点voidaddNodeToTaskNode(QStringfileName);//通过行号删除树的节点voidremoveNodeFromTaskNode(introw);mainwindow.cpp这是个容器用来放表格视图和树视图还有就是一些窗口的初始化和设置//导入设置voidloadSettings(){//软件的所有使用状态都是用通过QSettings来保存的}图5-8导入设置代码图//保存设置voidsaveSettings();图5-9保存设置代码图//任务出错voidtorrentError(TorrentClient::Errorerror){//如果在下载过程出现错误,提示错误图5-10出错处理代码图//添加TorrentbooladdTorrent();//删除任务voidremoveTorrent(int){主要是将所选的任务断开连接}//暂停任务voidpauseTorrent(int){ //将任务状态设为暂停}//任务中断voidtorrentStopped();}//更新任务状态voidupdateState(TorrentClient::Statestate);//更新PEER信息voidupdatePeerInfo();//更新进度条voidupdateProgress(intpercent);//更新下载速度voidupdateDownloadRate(intbytesPerSecond);//更新上载速度voidupdateUploadRate(intbytesPerSecond);//voidacceptFileDrop(constQString&fileName);//通过限制socket来现在下载和上传速度//设置最大上传速率限制voidsetUploadLimit(intbytes);//设置最大下载速率限制voidsetDownloadLimit(intbytes);系统测试测试概述G.J.Myers在他的名著《软件测试技巧》一书中,给出了测试的定义:“程序测试是为了发现错误而执行程序的过程”。根据这一定义,测试(Testing)的目的与任务可以描述为:目的:发现程序的错误;任务:通过在计算机上执行程序,暴露程序中潜在的错误。另一个与测试有关的术语叫纠错(Debugging)。它的目的与任务可以规定为:目的:定位和纠正错误;任务:消除软件故障,保证程序的可靠运行。测试与纠错的关系,可以用图7.1的数据流图来说明。图中表明,每一次测试都要准备好若干必要的测试数据,与被测试程序一道送入计算机执行。通常把程序执行需要的测试数据,称为一个“测试用例(TestingCase)”。每一个测试用例产生一个相应的“测试结果”。如果它与“期望结果”不相符合,便说明程序中存在错误,需要用纠错来改正。对于长度仅有数百行的小程序,测试与纠错一般由编码者一人完成;但对于大型的程序,测试与纠错必须分开进行。为了保证大程序的测试不受干扰,通常都把它交给独立的小组进行,等发现了程序有错误,再退回编码者进行纠错。有人把小程序得测试和纠错合称为“调试”。一旦编好了一个小程序,先拿到机器上测试,发现错误便进行纠错,修改后再重复测试。这一交替进行的“测试-纠错-再测试-再纠错”的过程,常被通俗的称为“调试程序”。其实“调试”在英语中并无相当的词,但纠错时有一种常用的工具叫“Debugger”,通常被称为调试程序,而不译为纠错程序。测试特性与分析、设计、编码等工作相比,程序测试具有若干特殊的性质。了解这些性质,将有助于我们正确处理和做好测试工作。挑剔性测试时对质量的监督与保证,所以“挑剔”和“揭短”很自然的成为测试人员奉行的信条。测试是为了证明程序有错,而不是证明程序无错。因此,对于被测程序就是要“吹毛求疵”,就是要在“鸡蛋里面挑骨头”。只有抱着为证明程序有错的目的去测试,才能把程序中潜在的大部分错误找出来。复杂性人们常常以为开发一个程序是困难的,测试一个程序则是比较容易的,这其实是误解。设计测试用例是一项需要细致和高度技巧的工作,稍有不慎就会顾此失彼,发生不应有的疏漏。举一个极简单的例子。假如一个程序的功能是输入3个数作为三角形的3条边,然后鉴别这一三角形的类别。输入3个”5”时程序回答“等边三角形”,但若输入3个“0”程序也回答“等边三角形”,就真假不分了。又如,三条便分别为2、3、4时应判断是“不等边三角形”,但如果对2、3、5或2、3、6也判断为“不等边三角形”,也会闹笑话。可见在设计测试用例时,需要考虑到各种可能出现的情况,对被测程序进行多方面的考核。切忌挂一漏万,把原本复杂的问题想的过于简单。小程序尚且如此,大型程序就可想而知了。所以有人认为,搞好一个大型程序的测试,其复杂性不亚于对这个程序的开发,主张挑选最有才华的程序员来参加测试工作。不彻底性“程序测试只能证明错误的存在,但不能证明错误不存在”。这句话揭示了测试所固有的一个重要性质――不彻底性。可能有人认为,测一遍不彻底可以测十遍,十遍不彻底可以测百遍。需要多少测试用例就用多少测试用例,难道还怕达不到彻底吗?为了回答这个问题,举一个例子。假如有人开发了一个C语言的编译程序,要对它进行彻底的测试,需要设计多少个测试用例呢?从正面说,该编译程序应能把一切符合语法的C程序正确的翻译为目标程序;从反面说,它应能对一切有语法错误的C程序指出程序的语法。显然,这两个“一切都是无穷量”,十无法实现的。所谓彻底测试就是让被测程序在一切可能的输入情况下全部执行一遍。通常称这种测试为“穷举测试(ExhaustiveTesting)”。实际测试中,穷举测试要不是像上例那样根本无法实现,就是工作量太大(例如一个小程序要连续测试许多年),在实践上行不通。这就注定了一切实际测试都是不彻底的,当然也就不能保证测试后的程序不存在遗留的错误。经济性既然穷举测试行不通,所以在程序测试中,总是选择一些典型的、有代表性的测试用例,进行有限的测试。通常把这种测试称为“选择测试(SelectiveTesting)”,为了降低测试成本(一般占整个开发成本的1/3左右),选择测试用例时应注意遵守“经济性”的原则。所以,第一,要根据程序的重要性和一旦发生故障将造成的损失开确定它的可靠性等级,不要随意提高等级,从而增加测试的成本;第二,要认真研究测试策略,以便能使用尽可能少的测试用例,发现尽可能多的程序错误。测试种类测试是一个执行程序的过程,即要求被测程序在机器上运行。其实,不执行程序也可以发现程序的错误。为便于区分,一般把前者称为“动态测试”,后者称为“静态分析(StaticAnalysis)”。广义的说,它们都属于程序测试。顾名思义,静态分析就是通过对被测程序的静态审查,发现代码中潜在的错误。它一般用人工方式脱机完成,故亦称为人工测试或代码评审(CodeReview);也可借助于静态分析器在机器上以自动方式进行检查,但不要求程序本身在机器上运行。按照评审的不同组织形式,代码评审又可区分为代码会审、走查盒办公桌检查3种。对某个具体的程序,通常只使用一种评审方式。代码会审是由一组人通过阅读、讨论和争议对程序进行静态分析的过程。会审小组由组长,2~3名程序设计和测试人员及程序员组成。会审小组在充分阅读待审程序文本、控制流程图及有关要求、规范等文件基础上,召开代码会审会,程序员逐句讲解程序的逻辑,并展开热烈的讨论甚至争议,以揭示错误的关键所在。实践表明,程序员在讲解过程中能发现许多自己原来没有发现的错误,而讨论和争议则进一步促使了问题的暴露。例如,对某个局部性小问题修改方法的讨论,可能发现与之有牵连的甚至能涉及到模块的功说明、模块间接口和系统总结构的大问题,导致对需求定义的重定义、重设计验证,大大改善了软件的质量。动态测试也可区分为两种。一类把被测程序看成一个黑盒,根据程序的功能来设计测试用例,称为黑盒测试(BlackBoxTesting);另一类则根据被测程序的内部结构设计测试用例,测试者需事先了解被测程序的结构,故称为白盒测试(WhiteBoxTesting)。结论在2014年2月份,我开始了我的毕业论文工作,通过两个多月的折腾,总算把毕业设计给完成了。论文的写作是一个艰苦而又漫长的过程,需要不断的进行精心的修改,不断地去研究各方面的文献,认真总结,虽然过程有些坎坷,经历将近2个月的努力,终于完成了毕业论文。在这次毕业论文的写作的过程中,我拥有无数难忘的感动和收获。记得大概是去年的12月份左右,拿到这个毕业设计的题目,当时心中咯噔一下,虽然以前也写过不是代码,但是对于BT下载来说还是感到十分陌生,可以说基本没有任何印象。对于该题目没有任何头绪的我,开始是上网查询关于BitTorrent协议的信息,渐渐开始熟悉了BitTorrent协议。说白了还是计算机与计算机之间进行通信,只是通信的时候需要遵守一些规定,规定怎么获取peer,怎么分配peer等等。大致Bt下载过程就是,BT首先在上传者端把一个文件分成了Z个部分,甲在服务器随机下载了第N各部分,乙在服务器随机下载了第M个部分,这样甲的BT就会根据情况到乙的电脑上去拿乙已经下载好的M部分,乙的BT就会根据情况去到甲的电脑上去拿甲已经下载好的N部分,这样就不但减轻了服务器端得负荷,也加快了用户方(甲乙)的下载速度,效率也提高了,更同样减少了地域之间的限制。比如说丙要连到服务器去下载的话可能才几K,但是要是到甲和乙的电脑上去拿就快得多了。所以说用的人越多,下载的人越多,大家也就越快,BT的优越性就在这里。而且,在你下载的同时,你也在上传(别人从你的电脑上拿那个文件的某个部分),所以说在享受别人提供的下载的同时,你也在贡献。了解BitTorrent协议工作原理之后,然后就是每天上网查资料了解QT的信号与槽机制,了解窗体与窗体之间是怎么进行通信的,开始了解种子文件的解析代码,编写相应的种子类,保存种子的信息,了解客户端怎么与Tracker服务端通信,还有就是peer与peer怎么通信,编写相应的类,最后开始编写搭建软件界面框架吗,之后每天只要有时间就抽出来试着写,一步一步,在查阅参考其他人的代码下,慢慢写出了基本能够实现基本功能的软件,从一个对这个知识毫无了解慢慢学会了下载知识,这本身就是对新知识学习和能力的提高!这次毕业设计加深我对QT的认识以及C++的学习认识,更加清楚地了解到了QT中核心和精华,信号与槽机制,更加深刻的了解到面向对象程序设计的开发模式。我深刻的认识到要想成为一名合格且牛逼的C++软件工程师还需要很长的路要走,并且很艰难,但我相信每次的软件开发都是对自我软件水平的检验和提升,可以看到自己的不足,当你能认识到这一点的时候也许就自我的提升和学习新知识的动力,希望自己在以后的道路上,走得越来越从容。参考文献王晓凯.基于P2P多播发现的FTPSERVER及FTP调度优化[D].郑州大学,2003年刘保言.对等(P2P)网络搜索技术的研究[D].重庆大学,2004年孙默.P2P网络安全模型的研究与设计实现[D].西安电子科技大学,2005年陆垂伟;纪鹏;王再明.一种新型网络技术——P2P网络模型[J].黄石理工学院学报,2006年03期李智昕,董健全,李威.新的匿名通信机制:基于P2P的匿名Socket的研究[J].计算机工程与应用,2004年15期何春,张再萍,张鹰.P2P网络技术的研究及应用[J].电脑学习,20
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- XX项目度建筑安装工程合同投标文件
- XX大厦外墙翻新工程合同2025
- 个人房屋买卖合同模板
- 2025年电子商务交易支付四方合作协议
- 产学研一体化合作协议合同
- 2025年厨艺强化训练合作协议
- 二人合作创业合同书
- 三人共同投资协议合同样本
- 上海市化工产品销售代理合同细则
- 个人房产抵押合同范文
- 成品移动公厕施工方案
- 二零二五版财务顾问保密与工作内容协议3篇
- 2025-2030年中国干混砂浆行业运行状况及发展趋势预测报告
- 2025年度部队食堂食材采购与质量追溯服务合同3篇
- 2025江苏盐城市交通投资建设控股集团限公司招聘19人高频重点提升(共500题)附带答案详解
- 新人教版一年级下册数学教案集体备课
- 2024托管班二人合伙的协议书
- 任务型阅读 -2024年浙江中考英语试题专项复习(解析版)
- 绘本 课件教学课件
- 大型央国企信创化与数字化转型规划实施方案
- pcn培训培训课件
评论
0/150
提交评论