Java通过TCP向C#发送整数时接收字节数组为空问题
Java TCP发送数据到C#接收失败问题
问题现象
通过TCP从Java程序向C#程序传输List<List<String>>数据,先发送JSON序列化后的数据长度(整数),再发送数据本身,但C#端接收的字节数组始终为空,改用BinaryReader读取整数长度结果仍为0。
双方相关代码
Java发送代码
public void SendData(List<List<String>> tooltips){ try { Gson gson = new Gson(); String jsonData = gson.toJson(tooltips); byte[] dataBytes = jsonData.getBytes(StandardCharsets.UTF_8); int totalBytes = dataBytes.length; DataOutputStream dos = new DataOutputStream(this.outputStream); dos.writeInt(totalBytes); dos.flush(); // Send the data using the output stream this.outputStream.write(dataBytes); this.outputStream.flush(); } catch (Exception e) { System.out.println(e.getMessage()); } }
Java连接代码
public SocketSender(String serverAddress, int serverPort) { this.serverAddress = serverAddress; this.serverPort = serverPort; try { this.socket = new Socket(this.serverAddress, this.serverPort); this.outputStream = this.socket.getOutputStream(); } catch (Exception e) { System.out.println(e.getMessage()); } }
C#接收代码
public static List<List<string>> ReceiveListOfLists(TcpClient client) { try { NetworkStream stream = client.GetStream(); byte[] lengthBuffer = new byte[4]; stream.Read(lengthBuffer, 0, lengthBuffer.Length); int dataLength = BitConverter.ToInt32(lengthBuffer, 0); // Read the data bytes byte[] dataBytes = new byte[dataLength]; int bytesRead = 0; while (bytesRead < dataLength) { bytesRead += stream.Read(dataBytes, bytesRead, dataLength - bytesRead); } var jsonData = Encoding.UTF8.GetString(dataBytes); // Deserialize the JSON data into a List of Lists of strings var tooltips = JsonConvert.DeserializeObject<List<List<string>>>(jsonData); return tooltips; } catch (Exception e) { throw; } }
C#连接代码
public class SocketManager { private Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); private TcpListener tcpListener = new TcpListener(IPAddress.Parse("127.0.0.1"), 5020); private TcpClient client; public SocketManager() { tcpListener.Start(); client = tcpListener.AcceptTcpClient(); } public List<List<string>> GetListOfStringList() { return SocketReceiver.ReceiveListOfLists(client); } }
问题原因
核心问题是字节序不匹配:Java的DataOutputStream.writeInt()默认采用大端字节序(Big-Endian),而C#的BitConverter.ToInt32()和BinaryReader.ReadInt32()默认采用小端字节序(Little-Endian),导致读取的长度值完全错误,后续读取数据自然失败。
另外,NetworkStream.Read()方法不一定会一次性读取到指定长度的字节,原代码未处理这种情况,可能导致长度读取不完整。
解决方法
1. 统一字节序
方案一:C#端转换字节序
修改C#读取长度的逻辑,将大端字节数组转为小端:
byte[] lengthBuffer = new byte[4]; int bytesRead = 0; // 确保读取完整的4字节长度 while (bytesRead < 4) { int read = stream.Read(lengthBuffer, bytesRead, 4 - bytesRead); if (read == 0) throw new IOException("连接断开"); bytesRead += read; } // 反转字节数组,大端转小端 Array.Reverse(lengthBuffer); int dataLength = BitConverter.ToInt32(lengthBuffer, 0);
方案二:Java端用小端发送长度
如果不想修改C#代码,Java端手动按小端字节序写入整数:
// 替换dos.writeInt(totalBytes); byte[] lenBytes = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN).putInt(totalBytes).array(); this.outputStream.write(lenBytes); this.outputStream.flush();
2. 确保完整读取数据
无论是长度还是内容,都要通过循环确保读取到指定长度的字节,避免因TCP流的分段特性导致读取不完整。
修正后的完整C#接收代码
public static List<List<string>> ReceiveListOfLists(TcpClient client) { try { NetworkStream stream = client.GetStream(); // 读取完整的4字节长度 byte[] lengthBuffer = new byte[4]; int bytesRead = 0; while (bytesRead < 4) { int read = stream.Read(lengthBuffer, bytesRead, 4 - bytesRead); if (read == 0) throw new IOException("读取长度时连接断开"); bytesRead += read; } // 转换大端字节序到小端 Array.Reverse(lengthBuffer); int dataLength = BitConverter.ToInt32(lengthBuffer, 0); // 读取完整的数据内容 byte[] dataBytes = new byte[dataLength]; bytesRead = 0; while (bytesRead < dataLength) { int read = stream.Read(dataBytes, bytesRead, dataLength - bytesRead); if (read == 0) throw new IOException("读取数据时连接断开"); bytesRead += read; } var jsonData = Encoding.UTF8.GetString(dataBytes); return JsonConvert.DeserializeObject<List<List<string>>>(jsonData); } catch (Exception e) { throw; } }
内容的提问来源于stack exchange,提问作者Fabio
相关产品推荐
相关产品推荐

