该篇设计主要针对文件传输异常,确保可恢复传送的机制。该机制,可以说是接收方每接收一块文件片段,需要重计算文件未接收片段。确保文件传输完整性。
一、如何计算未接收片段
二、实现类
该类主要针对接收端,根据文件长度,定义未接收片段,每一段,重计算未接收片段。若传输失败,则可以获取未接收片段。
package man.kuke.core;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
/**
* <p>文件片段池<p/>
*
*
* 断点续传:在接收过程中,若出现接收异常,希望能在下一次接收过程中,
* 接着上一次接收内容的基础上继续接收;即,接收过的内容不必再次传输。
* 对于文件级别的断点续传,相对简单,在更高层面,检查接收到的文件,和未接收的文件,再进行一
* 未接收文件的传输操作即可
*
* 对于大文件。再接收过程,如果已经接收了一部分,那么,需要知道哪些部分接收失败
* 下一次传输过程,只传输这个文件的部分内容
*
* 每接收一块文件片段,都可得到这个文件片段的offset和len
* 只要处理片段的数据,就可以得到未接收的文件片段数据
*
*
*/
public class UnreceiveSection {
/**
* 文件ID
*/
private long fileId;
/**
* 未接收片段
*/
private List<SectionHander> sectionHanderList;
public UnreceiveSection(long fileId,long fileLenth) {
this.fileId = fileId;
this.sectionHanderList = new LinkedList<>();
sectionHanderList.add(new SectionHander(fileId,0,fileLenth));
}
public UnreceiveSection(int fileId) {
this.fileId = fileId;
}
//TODO Test
/**
* 填充未接收片段列表
* 1、首先锁定填充区间
* 2、重新计算未填充片段,产生左片段,右片段
* @param sectionHander
* @return 片段接收是否完毕
*/
public boolean receiveSection(SectionHander sectionHander) {
for (int index = 0; index < sectionHanderList.size(); index++) {
SectionHander curSection = sectionHanderList.get(index);
long curStart = curSection.getOffset();
int curEnd = (int) (curStart + curSection.getLen() - 1);
long receiveStart = sectionHander.getOffset();
int receiveEnd = (int) (receiveStart + sectionHander.getLen() - 1);
if (curStart <= receiveStart && receiveEnd <= curEnd) {
//删除满足未接收片段,重新加入新片段
this.sectionHanderList.remove(curSection);
//当前区间右边界大于sectionHander的右边界
if (curEnd - receiveEnd > 0) {
//加入左片段
this.sectionHanderList.add(index,new SectionHander(fileId,receiveEnd + 1, (int) (curEnd - receiveEnd )));
}
//当前区间左边界小于sectionHander的右边界
if (receiveStart -curStart > 0) {
//加入右片段
this.sectionHanderList.add(index,new SectionHander(fileId,curStart, (int) (receiveStart -curStart )));
}
return isAllReceived();
}
}
System.out.println("分片[" + sectionHander + "] 不存在");
return true;
}
public List<SectionHander> getSectionHanderList() {
return sectionHanderList;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UnreceiveSection that = (UnreceiveSection) o;
return fileId == that.fileId;
}
@Override
public int hashCode() {
return Objects.hash(fileId);
}
public boolean isAllReceived() {
return sectionHanderList.isEmpty();
}
public Iterator<SectionHander> getIterator() {
return new Iter();
}
// 遍历未接收片段
private class Iter implements Iterator<SectionHander>{
private int index = 0;
@Override
public boolean hasNext() {
boolean next = index < sectionHanderList.size();
if (next) {
index = 0;
}
return next;
}
@Override
public SectionHander next() {
return sectionHanderList.get(index++);
}
@Override
public void remove() {
}
}
}