Android向Python服务器发送非ASCII字符数据时末尾字节丢失求助
解决UTF-8字符导致Socket传输数据截断的问题
问题根源
你的核心问题是混淆了字符数和UTF-8字节数:
- Android端发送的长度是字符串的字符数量(比如
é算1个字符),但UTF-8编码中这类非ASCII字符占2~4个字节; - Python服务器用这个字符数去读取字节,实际需要读取的字节数远大于字符数,导致只读到部分数据,剩余字节留在缓冲区,表现为JSON末尾截断。
修复方案
1. Android客户端修改:发送字节长度而非字符长度
必须先将字符串编码为UTF-8字节数组,计算字节数组的长度作为传输头部,再发送头部和字节数据:
private void send(String sendingStr) { try { // 定义与服务器一致的头部长度,比如4位 final int HEADER_LENGTH = 4; // 将字符串转为UTF-8字节数组 byte[] dataBytes = sendingStr.getBytes(StandardCharsets.UTF_8); // 把字节长度格式化为固定长度的字符串(补零填充) String lengthHeader = String.format("%0" + HEADER_LENGTH + "d", dataBytes.length); OutputStream outputStream = socket.getOutputStream(); // 先发送头部(编码为UTF-8字节) outputStream.write(lengthHeader.getBytes(StandardCharsets.UTF_8)); // 再发送实际数据字节 outputStream.write(dataBytes); outputStream.flush(); Log.d("Result", "已发送 " + dataBytes.length + " 字节"); } catch (Exception e) { Log.e("Exception", e.toString()); } }
2. Python服务器修改:按字节长度读取数据
服务器需要先读取固定长度的头部,解析出实际字节数,再读取对应长度的字节数据,最后解码为字符串:
HEADER_LENGTH = 4 # 与客户端保持一致 def recv_all(sock, total_length): """确保读取到指定长度的字节数据,处理网络分段传输""" received_data = b'' while len(received_data) < total_length: chunk = sock.recv(total_length - len(received_data)) if not chunk: return None # 连接已断开 received_data += chunk return received_data while True: client_socket, client_address_port = server_socket.accept() print(f"{client_address_port} 已连接") # 读取长度头部 header_bytes = recv_all(client_socket, HEADER_LENGTH) if not header_bytes: continue byte_length = int(header_bytes.decode('utf-8')) # 读取实际数据字节并解码 activity_data = recv_all(client_socket, byte_length) if not activity_data: continue activity_name = activity_data.decode('utf-8') print(f"收到: {byte_length} 字节 - {activity_name}") if activity_name: # 处理第二个数据块 header_bytes = recv_all(client_socket, HEADER_LENGTH) if not header_bytes: continue byte_length = int(header_bytes.decode('utf-8')) data_bytes = recv_all(client_socket, byte_length) if not data_bytes: continue data_string = data_bytes.decode('utf-8') print(f"收到: {byte_length} 字节 - {data_string}")
关键注意事项
- 客户端和服务器的
HEADER_LENGTH必须严格一致,建议设为4或8(足够覆盖大部分数据长度); - 永远不要用字符串的字符数作为传输长度,必须基于UTF-8编码后的字节数计算;
- 使用
recv_all这类封装函数处理网络传输,避免因网络分段导致的不完整读取。
内容的提问来源于stack exchange,提问作者preno1221
相关产品推荐
相关产品推荐

