java udp断点续传,用udp实现断点续传,采用滑动窗口,延时重发的思路

不知有没有现成好用的类,有的话还请告诉我一声,先谢谢了!

这个例子仅供学习参考。我原来觉得使用udp应该会比tcp快一些,但是既然要延时重发,也就是要保证连接可靠性;既然要可靠,不如干脆用tcp得了,tcp在传输层实现了滑动窗口和流量及拥塞控制,直接用serverSocket 编程简单一点,实现多线程下载也方便

一、滑动窗口,延时重发:我是这么实现的:其中用到了Thread.suspend()和resume()这些被Deprecated的方法,不过我用的时候倒是没出什么问题。

发送方Sender大概如下:实例域包括两个Thread和一个timer。代码因为和其他功能有些耦合,所以没有贴出来;这里只写个大概

public class Sender extends ThreadGroup{

private Thread t;//用来发送滑动窗口中的数据包

private Thread r;//用来监听接收方的响应从而移动滑动窗口

private javax.swing.Timer timer;//滑动窗口中的数据发送完后还没有接收到回应,就启动这个定时器,计时结束后从新发送滑动窗口中的数据

public Sender(){

t = new T(this,"t");

r = new R(this,"r");

timer = new Timer(2000,new ActionListener(){

public void run(){

t.resume();

}

}

}

public void join(){

t.join();

r.join();

}

private class T extends Thread{

public void run(){

while(!eof){

while(要发送的数据包在滑动窗口范围中){//滑动窗口只不过是两个指针指向窗口的头和尾

datagramSocket.send(datagramPakcet);

已发送的长度 += 数据包长度;

Thread.sleep(100);

}

timer.start();

suspend();

}

}

}

private class R extends Thread{

public void run(){

while(!eof){

datagramSocket.receive(datagramPacket);

接收到的packet中携带了接收方接收到了第几帧的信息,将移动窗口向前移动

timer.stop();

t.resume();

}

}

}

}

timer中还可以设置一下,比如重发5次没有应答就终止线程

接收方Receiver:实例域包括一个HashMap和一个Stack

接收时从stack中取出一个缓冲区用来接收,若接收到的这一帧是我要的下一针,就写入文件;否则先放入hashmap,等要的下一帧到了在从hashmap中取出,按顺序一起写入文件,写完后把缓冲区放会到stack中。每接收几帧后像发送方回应一下接收到哪里了

public Receiver extends Thread{

private HashMap map;

private Stack stack;

public void run(){

while(!eof){

byte buf = stack.pop();

datagramPacket.setData(buf);

datagramSocket.receive(datagramPacket);

packet数据头携带有第几帧的信息

if(该帧是在我的接收滑动窗口中){

map.put(id,datagramPacket.getData());

while((buf = map.remove(id++)) != null){

将buf写入文件;

stack.push(buf);

}

}

每接收5个数据包后向发送方回应一下;

}

}

}

二、断点续传

接收方接收文件时可以创建两个同名文件,一个后缀".aaa",一个后缀".bbb",.aaa的就是正在接收的文件,为接收完成后在把后缀aaa去掉;.bbb的文件用来记录信息,接收过程中不断把接收到了第几个帧写入.bbb文件中。这样即使接收到一半程序终止,下一次只要读取这个文件就能知道上次接收到哪里,向发送方发出请求时让它从这里开始发送就行了

三、发送文件夹

不知为什么网络上很少见能发送整个文件夹的,只能打包在发送。

其实发送文件夹很简单:

public void sendDirctory(File dir){

if(dir.isFile()){

Sender sender = new Sender(dir);

sender.start();

sender.join();//用join,使发送完这个文件在发送下一个

}

else{

File[] list = dir.list();

for(int i=0;i

sendDirectory(list[i]);

}

}

}

四、ByteBuffer类: ByteBuffer 可以对字节数组进行操作,可以从字节数组中读出和写入int,byte,long ,short等数据类型,和FileChannel配合使用挺方便的,就是要注意其中position 和 limit 指针的移动。 ByteBuffer 对读写数据包的包头信息很方便,byteBuffer.array()方法能转化成数组,然后用datagramPacket发送出去。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值