我想使用Java中的UDP DatagramPacket将从磁盘读取的视频文件传输到接收器。
关键点如下:尽管要从磁盘读取要传输的文件,但我应该假设我不知道文件的大小。需要增量读取整个文件,并且文件的数据报包的大小应有所不同。
简而言之,我应该假设我正在将实时视频流传输到接收器,而不知道我将完全需要发送多少数据以及将以什么速率生成数据。
现在,我有一个代码可以立即读取磁盘上的文件,并转换为数据报包以使用UDP套接字传输。但是我不知道如何在不知道原始文件大小的情况下打包文件并逐步读取会模拟视频实时流的文件。
使用Java实现此想法的任何投入都是非常有用的。基本功能正常运行后,我需要实施实时文件传输协议。
发件人:
File file = new File("/crazy.mp4");
FileInputStream fis = new FileInputStream(file);
DatagramPacket pack;
int size = 0;
byte[] buffer = new byte[((int) file.length())];
ByteBuffer bb = ByteBuffer.allocate(4);
bb.order(ByteOrder.BIG_ENDIAN);
while (true) {
size = fis.read(buffer);
pack = new DatagramPacket(buffer, buffer.length, address,
packet.getPort());
socket.send(pack);
}
接收方:
File file = new File("/crazyRecv.mp4");
FileOutputStream fos = new FileOutputStream(file);
DatagramPacket rpacket = new DatagramPacket(buffer, buffer.length);
while (true) {
socket.receive(rpacket);
fos.write(rpacket.getData(), 0, rpacket.getLength());
}
谢谢。
最佳答案
此发送和接收UDP数据包的代码不能保证在客户端成功地重新创建该文件。
UDP是不可靠的-没有像TCP中那样的低级确认和数据包重传机制,因此您必须实现这一点。数据包可能会丢失,并且永远不会在客户端收到
UDP不是顺序的-您不能仅仅期望UDP数据包顺序地在客户端接收。第一个数据包可能最后到达,最后一个数据包可能先到达,随后破坏文件。 TCP保证顺序传送。
如果仍要使用,则必须编写自己的应用程序级别协议。例如
您发送内容为“文件开始”的数据包
客户端为该“文件开始:已接收”发送一个ack数据包。
如果您没有收到“文件开始:已收到”,则必须转到步骤1
然后发送具有唯一ID“数据包1” +数据包数据的数据包
客户端为该“数据包1:已接收”发送一个ack数据包。
如果您没有收到“数据包1:已收到”,则必须转到步骤4
对所有数据包执行步骤4-6
您发送内容为“文件结束”的数据包
客户端为该“文件结尾:已接收”发送一个ack数据包。
如果未收到“文件结束:已收到”,则必须转到步骤8