java - 套接字(Java 中)。分割字节 block

标签 java sockets

假设您有一个连续的二进制数据流。每个数据片段都应该以某种方式进行分割。最好的方法是什么?

Socket.read(byte[] arr) 不保证您会收到与使用 Socket.write(byte[] arr) 发送的字节数完全相同的字节数,arr 可能会被分割(您首先读取的 10 个字节中 8 个字节)然后2)或拼接。

解决此问题的方法之一是首先指定传入字节数组的大小。正好读取 4 个字节,将它们转换为整数 x,然后读取 x 个字节。但这仅适用于 TCP,如果只有一次您发送错误的字节数组大小,则可能会完全搞乱一切

我能想到的另一种方法是用伪随机字节序列作为数据 block 的前缀。使用种子在客户端和服务器上初始化 Random,并使用其 random.nextBytes(byte[] arr) 作为前缀。它的缺点是,为了确保实际数据 block 中出现随机序列的可能性很小,您必须将其设置得很长。这会增加很多无用的流量。再说一遍,这不是 UDP 套接字的出路。

那么还有什么其他好的方法可以做到这一点?是否有任何简单的库可以让我简单地执行 conn.sendDataChunk(byte[] arr) ?

最佳答案

One of the ways of solving this is specifying incoming byte array's size first. Read exactly 4 bytes, convert them into an Integer x, then read x bytes.

是的,这正是你应该做的。换句话说,您在每条消息之前添加一个消息 header 。当您想要将基于消息的网络协议(protocol)分层在没有消息边界概念的基于流的网络协议(protocol)之上时,这是实际需要的。 (TCP 故意模糊 IP 数据包边界。)

您还可以以此为契机向邮件 header 添加其他字段,例如帮助您区分不同邮件类型的邮件 ID 号。

But this only works in TCP and may completely mess everything up if just one time you will send wrong byte array size.

这是真的。因此,不要发送格式错误的 header !

严肃地说,带有长度字段的 header 是标准做法。最好对长度添加健全性检查:确保它不会太大(或负值),这样您就不会最终分配 2GB 内存来读取下一条消息。

另外,也不要假设您可以使用单个 read() 读取整个 header 。可能需要多次读取才能获取整个 header 。

关于java - 套接字(Java 中)。分割字节 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26554716/

相关文章:

java - 使用 OnboardingSupportFragment 时内容重叠

java - 通过序列化在对象中发送 BufferedImage 的正确方法。写对象 读对象

java - Socket.connect() 到 0.0.0.0 : Windows vs. Mac

sockets - 文件流遇到缓冲区欠载/下溢?

javascript - Socket.io客户端没有收到来自服务器的消息

java - 编译器给我一个 'unreachable statment' 错误

Java 和 SQL : return null or throw exception?

Java - 如何检测 bash 是否已返回?

sockets - iSeries机器上PASE上的网络错误

java - 安卓 : application crashes with BadTokenException Error (trying to show AlertDialog)