基于P2P的局域网多线程共享软件设计论文

文章 2019-07-23 10:47:57 1个回答   ()人看过

1 系统概述

本系统的主要功能其一,局域网下的文件P2P共享,这里包括文件的传输和文件列表的传输;其二,局域网下用户的P2P心跳检测。系统的特点是多线程多任务同步。

2 设计思想

下面将从两个大模块来介绍设计思路,首先是文件的收发,然后是文件列表的收发和心跳模块,如图1所示。

2.1 文件收发模块

文件的收发是resource-shaie最基本的功能,也是最核心的功能。

2.1.1 有关文件收发的Socket的分类

因为这里采用的是TCP协议,所以在程序中,大体上存在于3组Socket,与文件收发有关,一组Socket是welcomesocket,用于监听连接的到来,并Accept;另一组Socket,是数据传输的Socket,来自于welcomesocket的accept(),用于send文件数据给对等方,姑且称作sendsocket;最后一组Socket也是数据传输的socket,通过connect()对等方的welcomesocket得到,与上面那个sendsocket是直接相连的,只是因为所面对的对象不同,对于当前对等方,因为这个Socket的用于recover文件,姑且称作recvsocket。

可以这样理解,对于一个对等方来说,sendsocket就只send(),recvsocket就只recover ()。之所以这样分开,是为了方便管理,降低耦合度,使得两个对等方之间的所直接相连的一对sendsocket和recvsocket在一个文件任务中维系关系,也就是说,一对socket,在同一时间只共同执行一个任务,一边是发和一边是收。然而,如果全在一个Socket中send和recv,就会变得很乱,一个socket就可能牵连多个任务,一个socket出了问题,可能几个任务的收发都会失败。

下面举一个例子来具体说明为什么要这样分类。

假使现在有两个人,hana和alice。考虑hana从alice下载一个文件的情况,在不考虑上传操作的时候,hana是主动的,alice是下载方,所以首先hana会connectalice的welcomesocket,而对于alice而言,她的welcomesocket一直在等待hana的接入,hana—旦发起连接她就会accept。接着,hana通过connect得到的socket就是所谓的recvsocket,而这个socket相对于alice,就是alice的sendsocket,她将从这个socket里接收数据,但是目前还不行,因为alice并不知道hana的要求是什么,所以这里需要向alice发送一个请求,同样是通过recvsocket。对于alice而言,假使已经从welcome socket accept到了一个sendsocket,那么首先要获取请求,她需要先对sendsocket执行一次recv请求的操作。

到这里,请求完成了,接下来,hana的recvsocket就不断接收文件数据,alice的sendsocket不断发送文件数据。反过来,假使alice想从hana那里下载东西,因为二人都有上述3组Socket,所以很容易实现。实际上,想实现上传功能也可以用完全一样的逻辑体系,只需要从后者发送一个特殊指令,使得前者发送一个下载请求给后者即可,如图2所示。

2.1.2 文件请求的监听和连接

上面讨论的是纯粹的传输一个文件的情况,下面内容逐渐复杂。

还是上面的例子,假设现在需要支持多任务的模式,也就是说,alice不仅仅要向hana—个人发送一个文件,而是将会向很多人发送文件,并且对于每个人,还不只是一个文件。

那么,alice可以开多个welcomesocket去listen,每一个welcomesocket监听n个用户,接着通过accept返回每一个文件的sendsocket,这样一来,就等于说和每一个终端都建立起了多个传送通道,每个传送通道传送一个文件,也就是一个任务。

现在问题是到底需要几个这样的welcomesocket?当然,可以只开一个welcome,全靠一个welcomesocket监听(用户数量)*(每个用户的文件请求数量)数量的请求。但在实际设计中,使用了多个端口创建了多个welcomesocket,让每一个welcomesocket对于每一个访问他的终端而言,在单个任务执行的过程中,只能有一个文件的请求。这样一来,每一个welcomesocket的最大并发连接数就一定是用户的总数量,而welcomesocket的数量就是由alice能够同时向一个终端send几个文件决定的。

也就是说,hana在前一个下载任务执行完关闭recvsocket以前,不能向同一个welcomesocket再一次发起connect,(当然因为welcomesocket的实体是在alice那边,所以hana在这里,实际上禁用了对于此welcomesocket的connect操作)这样做的目的是为了限制对于同一个用户的最大下载量。

所以,对于hana来说,假如她要从alice或者其他人那里下载多个文件,这就要求hana去connect那些用户的多个welcomesocket,在connect中传入的地址可能包涵每一个对象的IP和每一个传输port,所以hana的recvsocket最多可以和ip_num*port_num个数的sendsocket建立连接。(ip_num代表传送端数量,一个ip—台用户,port_num代表在一个ip下对于单用户支持的最大传输任务数量,那么,对于alice而言,

她最多同样可以同时传输ip_num*port_num个任务)而在每一次任务完成之后,hana都会关闭掉那个任务的recvsocket,并且将这个任务所对应的welcomesocket的禁用状态解除;与之对应的,alice在传送完之后,也会将sendsocket关闭。

通过图3来看这种情况,假使这次alice不仅要给hana发送文件,还要给自己的母亲发送文件,对于hana或者alice的母亲而言,最多同时从alice这里下载3个文件。

2.2 文件列表收发和心跳模块

2.2.1 动态心跳检测

前面说了P2P的文件传输机制,还讲了多任务多用户的情况,现在来说一下这个系统中的另一个很重要的机制,心跳机制。通过发送心跳信息和接收心跳,用来感知在局域网中,有哪些对等方是存在的,双方的心跳包中有少量的数据,一般而言包含用户的信息,比如用户名,终端系统信息之类的。只有知道哪些对等方式存在的,才能进一步的保存这些对等文件通信中的有用信息,(可能包括这个用户的文件列表,这个用户的各个welcomesocket的地址,等),最后根据这些信息才能真正地实现文件通信。

还是上面的那个例子,考虑了这样情况,hana先上线了,过了一段时间alice才上线。那么在alice上线的那一瞬间,如何使得两人都知道对方上线了呢,准确地说,是通过P2P软件上线。这就好比两台机器都上了网,并且都登上了QQ,但QQ判断是否上线,仅仅是有没有在QQ上线,而不是在SKYPE上线了,所以我们应该有一套自己的机制,这就是要介绍的心跳机制。

在这里,机制是这样实现的:不管对于hana或者alice,她们在上线的时候首先都会进行广播式的连接尝试,广播对象是子网网段下所有的IP地址。其次,她们还会单独为心跳建立一个welcomesocket,开一个监听的线程专门用于监听新上线用户的connect请求。在这里,判断是否在线的逻辑是 “收到某人的心跳包,就表示某人目前在线”。

在结合例子讲解之前,先讨论心跳机制中的socket分类。心跳的welcomesocket和文件传输的那个welcomesocket没有什么性质上的区别,无非就是拥有自己独特的端口号而已。但是,心跳的收发是没有sendsocket和recvsocket的这种概念的,只有一个heartsocket,这个socket是一个专门用于心跳收发的长连接socket,他一直存在,不会被close的,所以会被长期保存,这里要和之前说的用于文件传输的sendsocket和recvsocket区分,他们有很大的差异,首先,文件传输的send和recvsocket是不会长期保存的,一般只是一些函数中的局部变量,因为他经常改变,他传完一个任务就关闭了,下一次又重新生成,所以文件传输中这些收发socket属于短链接的socket,其次,在heartsocket中,发送和接收都是通过这一个socket。

举—个例子,假设hana首先上线,她先开启了心跳wel-comesocket的监听,这时候,alice并没有上线,所以有反馈,并且hana对子网内中所有ip的connect的尝试也都失败了。在这之后,alice上线了,首先alice的广播式connect尝试,成功激活了hana的welcomesocket的循环accept,成功连接之后,alice通过return的heartsocket,向hana发送一个心跳包,hana在accept之后会立马recv这个心跳包,hana接收到心跳包之后,就认为alice目前处于在线了,他也可以通过心跳包里的信息知道来自于这个ip的人的名字叫alice,接着她要做的是就是把这个heartsocket保存好,准备下一次收发心跳包。那么流程到此,hana已经知道alice的存在了,但是alice却还并不知道hana的存在,因为她还没有接受到hana的心跳包。所以,hana在接收到alice的心跳包之后,保存了相关信息后,她还会通过这个heartsocket发送一个心跳包给alice,而对于alice而言,在她发送完心跳包之后,她会马上recv对方的心跳包,这样一来,就使得alice也知道了hana的存在了。

在相互都知道对方的存在之后,大家通过这同一个heartsocket相互发送和接收心跳包了,每接收一个心跳包就代表目前对方是存在的,一旦接受超时,那么就代表对方下线了,这样就可以动态监测对方是否已经下线,如图4所示。

2.2.2 文件列表的收发

下面来讨论文件列表的收发。这个可以和之前的文件收发关联起来,因为文件列表在一般情况下是不会有变动的,故而没有必要一直重复接受对方的文件列表,仅仅是在第一次的时候和用户自己认为需要更新的时候再去接收新的文件列表。所以,可以知道的是,文件列表的socket也是一种短连接的socket,用完了关闭就行了,需要的时候再connect对方的welcomesocket。

同样,文件列表的传输是双向的,所以在设计中,基本上和之前说到的文件传输机制如出一辙,也是3个socket,welcomesocket,recvsocket,sendsocket。只不过,请求文件列表的那个人不需要发送那个所谓“文件请求”而已,connect之后,直接从recvsocket中接收就可以了。

3 类设计思想

由于篇幅有限,只能做一下思想的概述。根据需求,类设计包括:user,myself_user,task,task_manager。结合面向对象的思想,其中有两种类别,一种跟“用户”有关,另一种跟“任务”有关。

在设计中,何为“用户”,何为“任务”?具体概念,必须先弄清楚。用户这个对象,指的是局域网中的对等方,也就是P2P中的peer,可以是自己的电脑,也可以是别人的电脑,这里还有一个myself_user的类,这个对象指的是本机用户,并且是user的子类。任务则是指,对于自己电脑而言,每一个下载任务的实例,也就是说,你每一次向别的对等方请求一个文件,都会产生一个下载任务。

3.1 用户有关类

User:用户类的主要职能是保存peer的信息,包括ip、名字、welcomesocket的地址、heartsocket等。

Myself_user:作为user的子类,除了保存了普通用户应有的信息之外,还要保存一些自身独有的信息,以及为其他peer提供一些服务,包括有文件列表的传输服务,文件的传输服务。

世界就是图5这样的,进来的箭头表示请求,从自己出去的箭头表示反馈(也可以称作“提供”)

user_manager:这个类字面上就可以理解是用户管理器,主要职能就是动态监测用户状态。通过收发心跳包的手段来嗅探用户状态,然后更新用户管理器中的用户组,将不存在的删除,新上线的添加。除此之外,他也和myself_user是相辅相成的,他初始化myself_user,并开启myself_user的服务。所以在实际应用的时候,只需初始化user_manager,他就可以自己去初始化myself_user了。除此之外,文件列表的请求实际上也是从user_manager这里发送出去的,并且它也负责接受文件列表并更新某个user中所保存的文件列表。

3.2 任务有关类

Task:这个类代表了一个下载的任务信息的对象,包括任务名、对象ip、大小、已完成%,等。值得注意的是,它不仅能保存信息,真正的下载也要负责执行。从发送请求到接受文件,这些工作,一旦你run了这个任务,就会开始执行。

Task_manager:任务管理器类,它主要就是像用户管理器那样动态监测其中成员的状态,其中有3个集合,running中的任务、success的任务、error的任务。主要职能是根据实时

4 结语

从展示的可执行的程序的截图,程序在VS2013中调试没有问题,也生成了release版本,界面是用coco2dx写的,主要是考虑到可移植性,

顶一下 ()  踩一下 () 

 

本文标签:

[!--temp.ykpl--]


友情链接: