UDP协议本身并不支持大文件传输,因为UDP协议不保证数据的可靠性和顺序性,而且UDP数据包的大小也有限制。因此,在实现UDP传输大文件时,需要进行以下优化:分割文件、数据传输前协商、确认接收、重传机制。
当传输文件大小小于65535字节时,可以采用下面方式传输,若文件大小超过65535字节时,则见本文的3种方式。
DatagramSocket datagramSocket = new DatagramSocket();
// 最大65535字节
Path path = Paths.get("D:/105721.txt");
byte[] msg = Files.readAllBytes(path);
String content = new String(msg, "utf-8");
byte[] result = new byte[msg.length + 2];
// 接口信息类型
byte[] type = {(byte) 0xE0, (byte) 0x02};
System.arraycopy(type, 0, result, 0, type.length);
System.arraycopy(msg, 0, result, 2, msg.length);
DatagramPacket datagramPacket = new DatagramPacket(result, result.length, new InetSocketAddress("127.0.0.1", 50000));
datagramSocket.send(datagramPacket);
datagramSocket.close();
1、通过UDP协议传输单个文件
通过控制发送的频率,提高报文的传输的精准性;每包传输的报文大小默认最大为2048字节,若每包传输的报文大于2048字节则需设置相关参数。
DatagramSocket datagramSocket = new DatagramSocket();
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("D:/105721.txt"));
byte bytes[] = new byte[2048];
byte result[] = new byte[2050];
byte[] type = {(byte) 0xE0, (byte) 0x02};
byte[] end = "quit".getBytes();
while (bufferedInputStream.read(bytes,0, bytes.length) != -1){
// 接口信息类型
System.arraycopy(type, 0, result, 0, type.length);
System.arraycopy(bytes, 0, result, 2, bytes.length);
datagramSocket.send(new DatagramPacket(result,0,result.length,InetAddress.getByName("127.0.0.1"),50000));
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.arraycopy(type, 0, result, 0, type.length);
System.arraycopy(end, 0, result, 2, end.length);
datagramSocket.send(new DatagramPacket(result,0,result.length,InetAddress.getByName("127.0.0.1"),50000));
datagramSocket.close();
2、通过UDP协议传输多个文件
DatagramSocket datagramSocket = new DatagramSocket();
File file = new File("D:/aaa");
String[] fileList = file.list();
for (String fileName : fileList) {
String childFilePath = "D:/aaa" + "/" + fileName;
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(childFilePath));
byte bytes[] = new byte[2000];
byte[] type = {(byte) 0xE0, (byte) 0x02};
byte[] name = fileName.getBytes(StandardCharsets.UTF_8);
byte[] end = "quit".getBytes();
byte result[] = new byte[type.length + name.length + 2000];
int i = 0;
while (bufferedInputStream.read(bytes,0, bytes.length) != -1){
String s = new String(bytes);
System.out.println(s + i++);
System.arraycopy(type, 0, result, 0, type.length);
System.arraycopy(name, 0, result, type.length, name.length);
System.arraycopy(bytes, 0, result, type.length + name.length, bytes.length);
datagramSocket.send(new DatagramPacket(result,0,result.length,InetAddress.getByName("127.0.0.1"),50000));
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.arraycopy(type, 0, result, 0, type.length);
System.arraycopy(end, 0, result, type.length, end.length);
datagramSocket.send(new DatagramPacket(result,0,result.length,InetAddress.getByName("127.0.0.1"),50000));
}
datagramSocket.close();
3、通过UDP协议传输压缩包中的指定文件
DatagramSocket datagramSocket = new DatagramSocket();
// 读取指定压缩文件中的文件
String filename = "D:/aaa.zip";
String fileToRead = "111612.txt";
File inputFile = new File(filename);
ZipFile zipFile = new ZipFile(inputFile);
ZipEntry entry = zipFile.getEntry(fileToRead);
InputStream inputStream = zipFile.getInputStream(entry);
BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
byte bytes[] = new byte[2000];
byte[] type = {(byte) 0xE0, (byte) 0x02};
byte[] name = fileToRead.getBytes(StandardCharsets.UTF_8);
byte[] end = "quit".getBytes();
byte result[] = new byte[type.length + name.length + 2000];
int i = 0;
while (bufferedInputStream.read(bytes,0, bytes.length) != -1){
String s = new String(bytes);
System.out.println(s + i++);
System.arraycopy(type, 0, result, 0, type.length);
System.arraycopy(name, 0, result, type.length, name.length);
System.arraycopy(bytes, 0, result, type.length + name.length, bytes.length);
datagramSocket.send(new DatagramPacket(result,0,result.length,InetAddress.getByName("127.0.0.1"),50000));
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.arraycopy(type, 0, result, 0, type.length);
System.arraycopy(end, 0, result, type.length, end.length);
datagramSocket.send(new DatagramPacket(result,0,result.length,InetAddress.getByName("127.0.0.1"),50000));
datagramSocket.close();
注:以上3种方式只做参考,具体还需根据场景修改,且传输完成的文件会比原文件在文档的最后多n行内容,因为设定的每包传输的报文大小为2000字节。