Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
套接字(Java)。分割字节块_Java_Sockets - Fatal编程技术网

套接字(Java)。分割字节块

套接字(Java)。分割字节块,java,sockets,Java,Sockets,假设您有一个连续的二进制数据流。每个数据片段都应该以某种方式分割。最好的方法是什么 Socket.read(byte[]arr)不能保证您收到的字节数与使用Socket发送的字节数完全相同。write(byte[]arr)arr可以拆分(从10个字节中先读取8个,然后读取2个)或拼接 解决此问题的方法之一是首先指定传入字节数组的大小。精确读取4个字节,将其转换为整数x,然后读取x个字节。但这只在TCP中起作用,如果只发送一次错误的字节数组大小,可能会完全搞乱一切 我能想到的另一个方法是用伪随机字

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

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

解决此问题的方法之一是首先指定传入字节数组的大小。精确读取4个字节,将其转换为整数x,然后读取x个字节。但这只在TCP中起作用,如果只发送一次错误的字节数组大小,可能会完全搞乱一切

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

那么,还有什么好的方法可以做到这一点呢?有没有简单的库可以让我简单地执行conn.sendDataChunk(byte[]arr)

解决此问题的方法之一是首先指定传入字节数组的大小。精确读取4个字节,将其转换为整数x,然后读取x个字节

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

您还可以借此机会向消息头添加其他字段,例如消息ID号,以帮助您区分不同的消息类型

但这只在TCP中起作用,如果只发送一次错误的字节数组大小,可能会完全搞乱一切

这是真的。所以不要发送格式错误的标题

严肃地说,带有长度字段的标题是标准做法。在长度上添加健全性检查是个好主意:确保长度不太大(或为负数),这样就不会为读取下一条消息分配2GB内存


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

关于UDP套接字:读取UDP套接字与读取TCP套接字不同。您要么获得UDP数据包,要么不获得。发件人:

数据报–数据包单独发送,只有在到达时才检查完整性。数据包具有明确的边界,在接收时将遵守这些边界,这意味着在接收方套接字上的读取操作将产生最初发送的整个消息

因此,对于UDP,您不必担心读取的字节数不正确。但是,如果某些数据没有到达,或者数据到达的顺序与发送的顺序不同,您确实需要担心会发生什么