我有一个Java客户端,它将UTF-8字符串发送到C#TCP-Server,我正在使用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),整个过程都有效,这显然不是解决方案。 我错过了什么?
答案 0 :(得分:7)
flush()
不保证数据包被发送出去。您的TCP / IP堆栈可以自由捆绑数据以实现最高效率。更糟糕的是,您和目的地之间可能存在大量其他TCP / IP堆栈,并且可以自由地执行相同操作。
我认为你不应该依赖数据包捆绑。在数据中插入逻辑终结符/分隔符,您将处于安全的一面。
答案 1 :(得分:2)
您不必担心数据如何分解为数据包。
您应该在邮件中包含字符串的长度,然后在接收端首先读取长度。所以例如发送你会做
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,但如果您这样做,则无法保证数据包的传送。
答案 2 :(得分:1)
Socket发送数据流,而不是消息。 您不应该依赖收到的数据包与发送的数据包相同。 如您所见,数据包可以组合在一起,但它们也可以分解。 使用@Chad Okere关于如何确保在发送阻止时获得阻止的建议。
但是在你的情况下,你可以使用
dataOutputStream.writeUTF(ar); // sends a string as UTF-8
和
String text = dataInputStream.readUTF(); // reads a string as UTF-8