java - 如何从 Java 发送一个 4 字节的 header 并在 Python 中读取它?

标签 java python tcp bytearray

我正在尝试从 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/

相关文章:

java - RuntimeException 无法启动 Activity : Permission Denial: broadcast from android asks to run as user -1 but is calling from user 0

java - 这是什么意思 'Parsing a text file or data stream' 是否适用于可序列化

python - Flask-Bootstrap、flask-wtf、添加类以提交按钮

python - 安装成功后CircleCI python模块导入报错

tcp - 使用tcp/ip socket实现服务器的最佳编程语言

c# - 如何使用套接字正确发送和接收字节/文件?

java - 如何在应用程序启动时触发 servlet 执行?

python - 我收到此错误 --> TypeError : string indices must be integers

c# - 为正确的数据传输构建 TCP 消息

java - 取消定时器