我目前正在使用java.net.Socket从客户端发送消息并从服务器读取消息。到目前为止,我的所有信息都相当短暂,我从来没有遇到任何问题。
我的一位朋友注意到我没有处理消息碎片,数据可能会碎片化,并建议我应该创建一个缓冲区来处理这个问题。我坚持认为TCP会为我处理这个问题,但我并不是百分之百确定。
谁是对的?
此外,我计划将来在C中创建一个客户端。 Berkeley套接字是否处理消息碎片?
详细信息:目前,在Java中,服务器创建一个套接字并使用InputStream #read()从消息中读取第一个字节。第一个字节确定整个消息的长度,并创建一个适当长度的字节数组,并调用InputStream#read(byte [])一次,并假定已读取整个消息。
答案 0 :(得分:3)
如果您正在谈论WebSockets,您可能会混合使用不同的概念。
有一件事是TCP / IP消息碎片。
其他的是缓冲是如何工作的。您读取数据缓冲区,并且需要一个框架协议,告诉您何时有完整的“消息”(或框架)。基本上你:
其他不同的是WebSocket消息碎片。 WebSocket已经有一个成帧协议,消息可以分成不同的数据帧,控制帧可以与数据帧交织:https://developer.mozilla.org/en-US/docs/WebSockets/Writing_WebSocket_servers#Message_Fragmentation
如果您正在编写WebSocket客户端或服务器,则必须为这种情况做好准备。
答案 1 :(得分:1)
扩展nos所说的,TCP会将大型消息分解成更小的块,如果消息足够大, 。通常,它不是。通常情况下,您编写的数据已经分成(由您)部分,分成有意义的块,如离散消息。
关于读取/写入不同调用量的内容来自于数据的写入方式,数据传输方式以及读取方式。
如果您写入2个字节100次,然后20秒后再读取,则会说有200个字节需要读取,如果需要,您可以一次读取所有字节。如果你传递一个巨大的2mb缓冲区要写(我甚至不知道那是否可能),写出来需要更长的时间,给予阅读程序更多的机会来获得不同的读取调用。
答案 2 :(得分:1)
详细信息:目前,在Java中,服务器创建一个套接字并使用InputStream #read()从消息中读取第一个字节。第一个字节确定整个消息的长度,并创建一个适当长度的字节数组,并调用InputStream#read(byte [])一次,并假定已读取整个消息。
那不行。查看InputStream.read(byte[]).
的合同。它没有义务传输多个字节。正确的方法是读取长度字节,然后使用DataInputStream.readFully(),
,它有义务填充缓冲区。