Java Socket的writeUTF()和readUTF()方法

12

我一直在阅读一些Java套接字代码片段,发现一个事实,即在套接字通信中,为了按顺序发送消息,您不必手动将它们分开,写入器/读取器流会自动为您完成。这是一个例子:

writer.java
writeUTF("Hello");
writeUTF("World");


reader.java
String a=readUTF(); // a=Hello
String a=readUTF(); // b=World

我试过这段代码,它可以正常工作。但是,我想知道这种编码风格是否应该正常工作。在不显式分隔每个片段的情况下,使用套接字流的潜在风险有哪些?


“明确地分离每个段”是什么意思?在TCP中甚至没有办法做到这一点,假设您所说的是RFC中的真实TCP段。请澄清您的问题。 - user207421
通常我会在文本中添加一些特殊字符,比如"###",然后在读取端检测它们。这有点傻,但我没有其他办法。 - Longbiao CHEN
3个回答

29

writeUTF()readUTF() 方法会先写入该字符串的长度(按照 UTF-8 编码时的字节数), 然后再写入数据,它们使用了修改过的 UTF-8 编码。因此存在一些潜在问题:

  • 使用这种方式处理的字符串最大长度为 65535,当字符串包含非 ASCII 字符时,其长度可能更小 - 在这种情况下很难准确预测限制,除非保守地假设每个字符占用 3 个字节。所以如果确定永远不会发送超过约 20k 的字符串,则可以放心使用。
  • 如果应用程序需要与其他语言编写的代码通信,那么另一端可能会难以处理修改过的 UTF-8 编码。但是对于应用程序内部通信,则无需担心这个问题。

2
根据文档,readUTFwriteUTF方法使用修改后的UTF8版本工作,该版本还在开头添加了要读取的字符的长度。
这意味着读操作将等待足够的字符被获取后才返回字符串。这意味着它们实际上是分段的,即使您仅仅是用DataInputStreamDataOutputStream装饰套接字流时也是如此。
总之,是的,它应该是相当安全的,因为API本身将负责分离单个消息。

0

java.net.Socket 运行良好,流等待 readUTF();

但是当使用 mina 的 CumulativeProtocolDecoder 时,它不会运行良好,抛出 java.io.EOFException


1
我严重怀疑那个说法是否正确。当对等方关闭连接时,会抛出 EOFException 异常。如果读取的数据仍然不完整,则预计会抛出 SocketTimeoutException 异常。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接