0

我有一个将 UTF-8 字符串发送到 C# TCP 服务器的 Java 客户端,我正在使用 DataOutputStream 发送字符串。代码如下所示:

public void sendUTF8String(String ar) {
    if (socket.isConnected()) {
        try {
            dataOutputStream.write(ar.getBytes(Charset.forName("UTF-8")));
            dataOutputStream.flush();
        } catch (IOException e) {
            handleException(e);
        }
    }
}

问题是冲洗似乎无法正常工作。如果我发送两个彼此靠近的字符串,服务器只会收到一条包含两个字符串的消息。如果我在调用之间执行 Thread.sleep(1000) ,那么整个事情都有效,这显然不是一个解决方案。我错过了什么?

4

3 回答 3

7

flush()不保证数据包被运走。您的 TCP/IP 堆栈可以自由地捆绑您的数据以实现最高效率。更糟糕的是,在你和你的目的地之间可能还有一堆其他的 TCP/IP 堆栈,它们可以自由地做同样的事情。

我认为您不应该依赖数据包捆绑。在您的数据中插入一个逻辑终止符/分隔符,您将是安全的。

于 2009-12-05T13:49:23.677 回答
3

您不必担心数据是如何分解成数据包的。

您应该在消息中包含字符串的长度,然后在接收端首先读取长度。所以例如发送你会做

byte[] arbytes = ar.getBytes(Charset.forName("UTF-8"));
output.writeInt(arbytes.length)
output.write(arbytes)

然后在你的读者中你做

byte[] arbytes = new byte[input.readInt()];
for(int i = 0; i < len; i++){
     arbytes[i] = input.read();
}
//convert bytes back to string.

您不能只调用 input.read(arbytes) 因为 read 函数不一定读取数组的整个长度。你可以做一个循环,一次读取一个块,但代码有点复杂。

无论如何,你明白了。


此外,如果您真的想控制数据包中的内容,您可以使用Datagram Sockets,但如果您这样做,则无法保证数据包的传递。

于 2009-12-05T14:46:02.930 回答
1

套接字发送数据流,而不是消息。您不应依赖收到的数据包与发送的数据包大小相同。如您所见,数据包可以组合在一起,但也可以分解。使用@Chad Okere 的建议,了解如何确保您获得与发送的块相同的块。

但是,在您的情况下,您可以使用

dataOutputStream.writeUTF(ar); // sends a string as UTF-8

String text = dataInputStream.readUTF(); // reads a string as UTF-8
于 2009-12-06T08:53:36.170 回答