简单的P2P电影下载加速,(类似迅雷下载电影P2P加速)

来源:互联网 发布:python 多次try 编辑:程序博客网 时间:2024/05/01 02:46

     捣鼓了几天,终于弄好了这小东西,记录一下学习过程。

      

    P2P的概念很久就听说了,什么P2P游戏加速之类的,感觉挺难的,所以也没打算自己动手去做= =。直到不久前,看到迅雷下载电影时,有什么高速通道加速,P2P加速之类的,又让我想起了P2P,同时,学长也给我简单的说了说P2P下载加速的原理。大概就是,每个用迅雷客户端下载电影的用户,下载电影时,迅雷都会记录下标志用户的IP地址等,还有标志电影的信息,以及保存路径。当另一用户再用迅雷下载同一电影资源的时候,迅雷查找服务器数据库,找到拥有已经下载过的用户,让这次请求用户去请求那个拥有资源的用户,下载部分资源。当有多个可用的用户(服务器)时,当存在一些网络环境较好的通道时,下载速度会提升,每个用户既当服务器,又当客户端,这就是P2P。


   于是从那时候起我就在捉摸着这东西,直到暑假才真正开始做。


   首先用Servlet写了个简单的服务器,建了个数据库,模拟迅雷记录用户下载信息,包括ip,端口,保存路径,电影名,大小,状态等。写了一些获取数据接口包括改变用户在线状态,用来标志用户是否打开软件,每当打开软件就启动一条ServerSocket线程处理请求。再有一个接口就是根据用户请求的电影资源名,找到数据库中拥有相同资源的,在线的其他用户,返回给客户端,还有一个接口就是更新端口和其他数据的接口。


    接下来就是具体思路。


    每当用户启动软件的时候,访问服务器改变自己在线的状态,另外启动一个线程来生成一个ServerSocket对象,来不断处理来的请求。软件界面上只有简单的电影资源名输入框,一个下载按钮,(其他判断之类的就做得不那么细致,一切主要为了下载),得到请求电影资源名之后,访问服务器获得拥有相同资源的的在线用户的信息,用Arraylist保存返回,客户端变针对每个可用的用户服务器启动一条线程访问。得到电影的具体信息之后,新建一个任务池,我这里的任务池是根据电影资源大小和可用用户服务器的个数建立的,尽量使每个任务大小初始化一致,最后一个任务可能有偏差。还定义了一些获得任务,添加任务的方法。

public class TaskPool {public List<Task> tasks = new ArrayList<Task>();//try to equal each task , or the last task is lesspublic TaskPool(long size,int amount){long average = size/amount;if((average*amount) == size){for(int i=0;i<amount;i++){tasks.add(new Task(i*average,(i+1)*average));}}else{for(int i=0;i<amount;i++){tasks.add(new Task(i*average,(i+1)*average));}tasks.add(new Task(average*amount,size+1));}}//get a random task from taskPoolpublic synchronized Task getTask(){int task_amount = tasks.size();if(task_amount != 0){Random r = new Random();int position = r.nextInt(task_amount);Task task = tasks.remove(position);return task;}else{return null;}}//add a taskpublic synchronized void addTask(Task task){tasks.add(task);}}


   具体访问就是先与可用用户服务器建立socket连接,首先在作业池中随机获取一个作业,往用户服务器发送一个代表作业的json字符串,其中每个作业包含了起始字节,终止字节,电影资源路径等。用户服务器接受了任务的json字符串,然后开始找到电影资源,往流里面写入任务的字节范围,客户端不断读取。读取完毕之后再重复从作业池中取出作业,循环执行上述过程。直到作业池为空,代表电影下载完成。


   但是有一个要注意的点,用户服务器有可能在任意时刻断开链接,那么此时客户端在每次读取数据的时候记录成功完成的字节数,当用户服务器断开链接的时候,它本身的任务没有完成,则将剩下的任务重新当做新任务加入作业池。由其他可用用户服务器执行。

catch (IOException e) {// server may disconnect suddenly,record the receiveBytes, and add //into taskPool as a new Task //(with new star)if(receiveBytes != (end - start)){Constant.taskPool.addTask(new Task(start+receiveBytes,end));}


   大体思路就是这样,我觉得需要注意的地方是下载边界的控制,以及一些边界字节的处理,还有断开链接的处理,异常处理。


   有兴趣看源码的前辈可以到 https://github.com/Downey-W/P2PSpeedUp     


    谢谢!

0 0
原创粉丝点击