0x00. 解决思路
- Sever端负责接收指令(文件路径、第几块、每块大小),读取相应的文件中的块数据,返回给Client(顺便附上有效数据长度、MD5)。
- Client端负责控制断点,通过断点向Server发送指令,接收数据后判断数据完整性(有效数据长度、MD5),再将数据写入目标文件。
- 由于Java流处理类实在繁多,本次实验就统一采用
In/OutputStream
和FileIn/FileOutputStream
字节流传输类来传输数据。 - 多线程的Server还没摸清楚,这里就只用单线程了。
- Client发给Server的指令为UTF-8编码的字符串,格式为
文件路径|第几块|每块大小
。 - Server发送给Client的数据为字节数组,格式为:
数据长度,4字节int 数据MD5,16字节数组 文件块数据,长度由 数据长度
指定
0x01. Server端实现
-
监听端口,等待Client连接:
ServerSocket server = new ServerSocket(port); // 监听localhost:port Socket handle = server.accept(); // 等待Client接入 OutputStream out = handle.getOutputStream(); InputStream in = handle.getInputStream();
-
设定指令缓冲区:
final int orderBufSize = 1024; byte[] orderBuf = new byte[orderBufSize];
-
一直监听指令,直到Client结束:
while (true) { // 接收并解析Client发过来的指令 // 通过指令读取指定文件中的指定块 // 数据附上有效数据长度和MD5值 // 将数据发送给Client } // 关闭连接
-
接收并解析Client发过来的指令:
// 接收指令 int orderLen = in.read(orderBuf, 0, orderBufSize); if (orderLen <= 0) { break; } String orderStr = new String(orderBuf, 0, orderLen, "UTF-8"); // 解析指令 String[] orders = orderStr.trim().split("\\|"); // 正则表达式,用竖线分割字符串 final String filePath = orders[0]; // 目标文件路径 final int pieceIndex = Integer.parseInt(orders[1]); // 目标数据块 final int pieceBufSize = Integer.parseInt(orders[2]); // 每块大小
-
读取指定文件中的指定块:
byte[] pieceBuf = new byte[pieceBuf
-