一个简单的TCP模拟实现(五)
传输文件
- FileTransmit.java
package main.thread;
import main.MUTPInterface.RecvACKHandleInterface;
import main.common.DataPacket;
import main.common.DataPacketFactory;
import main.common.MutpConst;
import main.utils.PacketUtil;
import main.utils.PropertiesReader;
import org.apache.log4j.Logger;
import java.io.*;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
/**
* Created by liqiushi on 2017/11/24.
*/
public class FileTransmit implements Runnable {
//滑动窗口
/*1. 发送的文件分成一个一个有相应序号对应的小包
2. 根据对面的ACK反应情况,看是否需要重传*/
private Logger logger = Logger.getLogger(FileTransmit.class);
//private int windowSizeMaxium = 5;
private int lastSend = 5;
private RecvACKHandleInterface impl = null;
DatagramSocket cliSocket;
InetSocketAddress dstSocketAddr;
public FileTransmit(RecvACKHandleInterface impl, DatagramSocket cliSocket, InetSocketAddress dstSocketAddr) {
this.impl = impl;
this.cliSocket = cliSocket;
this.dstSocketAddr = dstSocketAddr;
}/**
* 应用层所有传输的数据
*
* @param accessFile
* @return
* @throws IOException
*/
public Map readFileInMap(RandomAccessFile accessFile) throws IOException {
Map allPackets = new HashMap<>();
//读取文件流
int readSize = -1;
int count = 2;
int bufSize = Integer.parseInt(PropertiesReader.getInstance().getValue("bufSize"));
byte[] buf = new byte[bufSize];
while ((readSize = accessFile.read(buf, 0, buf.length)) != -1) {
byte[] tmpBuf = new byte[readSize];
System.arraycopy(buf, 0, tmpBuf, 0, readSize);
allPackets.put(count, tmpBuf);
count += readSize;
}
return allPackets;
}@Override
public void run() {
//读取文件到一个Map里,来模拟
//分为4段 1 已经被ACK的,则移除掉 2 在窗口中,且已发送但并未ACKED 3 在窗口中,将要发送的
//4 窗口外,不允许发送的
Map allPackets = null;
Map slidingWindow = null;
try {
RandomAccessFile accessFile = new RandomAccessFile(PropertiesReader.getInstance().getValue("uploadFile"), "r");
allPackets = readFileInMap(accessFile);
//发送
int sendSizeLimit = impl.getSendSizeLimit();
for (int i = 0;
i < sendSizeLimit;
i++) {
int lastSentByte = impl.getLastSentedByte();
DataPacket dpk = DataPacketFactory.getInstance(MutpConst.DATA_ONLY);
if (lastSentByte == -1) {
//第一次发送
dpk.setBuf(allPackets.get(2));
dpk.getHeader().setSeqNum(2);
impl.setLastSentedByte(2 + dpk.getBuf().length - 1);
} else {
//假设发送seq = 3 3是第一个字节序号,3、4,下一个发5-----
dpk.setBuf(allPackets.get(lastSentByte + 1));
if (dpk.getBuf() == null) {
logger.info("null"+lastSentByte + 1);
return;
}
dpk.getHeader().setSeqNum(impl.getLastSentedByte() + 1);
impl.setLastSentedByte(lastSentByte + dpk.getBuf().length);
}
PacketUtil.sendPackt(cliSocket, dstSocketAddr, dpk);
// 定时任务
new TimerCheckout(impl,dpk,cliSocket,dstSocketAddr).goTask();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
logger.info("readFileInMap error!");
e.printStackTrace();
}
}
}
推荐阅读
- 热闹中的孤独
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 放屁有这三个特征的,请注意啦!这说明你的身体毒素太多
- 一个人的旅行,三亚
- 布丽吉特,人生绝对的赢家
- 慢慢的美丽
- 尽力
- 一个小故事,我的思考。
- 家乡的那条小河
- 《真与假的困惑》???|《真与假的困惑》??? ——致良知是一种伟大的力量