我正在尝试从 Java 应用程序通过 TCP 套接字发送消息并在 Python 2.7 中读取它 我希望前 4 个字节指定消息长度,所以我可以这样做:
header = socket.recv(4)
message_length = struct.unpack(">L",header)
message = socket.recv(message_length)
在 Python 端。
Java 端:
out = new PrintWriter(new BufferedWriter(new StreamWriter(socket.getOutputStream())),true);
byte[] bytes = ByteBuffer.allocate(4).putInt(message_length).array();
String header = new String(bytes, Charset.forName("UTF-8"));
String message_w_header = header.concat(message);
out.print(message_w_header);
这对某些消息长度(10、102 个字符)有效,但对其他消息长度(例如 1017 个字符)无效。在失败值的情况下,如果我输出我得到的每个字节的值:
Java:
Bytes 0 0 3 -7
Length 1017
Hex string 3f9
Python:
Bytes 0 0 3 -17
Length 1007
Hex string \x00\x00\x03\xef
我认为这与 Java 中的带符号字节和 Python 中的无符号字节有关,但我无法弄清楚我应该怎么做才能让它工作。
最佳答案
问题出在 Java 端——b'\x03\xf9'
不是有效的 utf-8 字节序列:
>>> b'\x03\xf9'.decode('utf-8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf9 in position 1: invalid start byte
似乎 new String(bytes, Charset.forName("UTF-8"));
使用了 'replace'
错误处理程序 b'\xef'
是 '\ufffd'
的三个字节中的第一个 Unicode 替换字符以 utf-8 编码:
>>> b'\x03\xf9'.decode('utf-8', 'replace').encode('utf-8')
b'\x03\xef\xbf\xbd'
这就是为什么您在 Python 中收到 b'\x03\xef'
而不是 b'\x03\xf9'
的原因。
要修复它,请发送 Java 字节而不是 Unicode 文本。
无关,sock.recv(n)
可能返回少于 n
字节。如果套接字阻塞;您可以使用 file = sock.makefile('rb')
创建一个类似文件的对象并调用 file.read(n)
以准确读取 n
字节。
关于java - 如何从 Java 发送一个 4 字节的 header 并在 Python 中读取它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22693878/