从C#客户端向Java服务器发送一个4字节的消息头

从C#客户端向Java服务器发送一个4字节的消息头,c#,java,sockets,C#,Java,Sockets,我正在尝试将一个C#客户机写入一个用Java编写的服务器。服务器需要一个4字节(Java中的DataInputStread readInt())的消息头,后跟实际消息 我对C#完全陌生,如何将此消息头发送到Java服务器?我尝试了几种方法(大多是反复尝试,没有深入到C语言中),但没有任何效果。Java端的消息长度不正确(非常大)。这很简单,但您是否检查了endianness?很可能是您发送的数据和接收的数据之间的结尾不匹配。我不知道C,但您只需要执行以下等效操作: out.write((len

我正在尝试将一个C#客户机写入一个用Java编写的服务器。服务器需要一个4字节(Java中的DataInputStread readInt())的消息头,后跟实际消息


我对C#完全陌生,如何将此消息头发送到Java服务器?我尝试了几种方法(大多是反复尝试,没有深入到C语言中),但没有任何效果。Java端的消息长度不正确(非常大)。

这很简单,但您是否检查了endianness?很可能是您发送的数据和接收的数据之间的结尾不匹配。

我不知道C,但您只需要执行以下等效操作:

out.write((len >>> 24) & 0xFF);
out.write((len >>> 16) & 0xFF);
out.write((len >>>  8) & 0xFF);
out.write((len >>>  0) & 0xFF);

如果要交换大量数据,我建议实现(或找到)一个流包装器,它可以按网络顺序写入和读取int。但是,如果你真的只需要写长度,那么可以这样做:

using(Socket socket = ...){
  NetworkStream ns = new NetworkStream(socket);      
  ns.WriteByte((size>>24) & 0xFF);
  ns.WriteByte((size>>16) & 0xFF);
  ns.WriteByte((size>>8)  & 0xFF);
  ns.WriteByte( size      & 0xFF);
  // write the actual message
}

正如其他海报所指出的那样,它可以归结为endianness

Java希望数据是(网络字节顺序)。从Mono文档(对于类似的等价物)判断,C#趋向于小端(Win32/x86的默认值)

因此,当您使用标准类库将32位int“1”更改为字节时,它们会产生不同的结果:

//byte hex values
Java: 00 00 00 01
  C#: 01 00 00 00
您可以改变用C#编写整数的方式:

编辑:

更安全的方法是:

private static void WriteToNetwork(System.IO.BinaryWriter stream, int n) {
    n = System.Net.IPAddress.HostToNetworkOrder(n);
    stream.Write(n);
}

这里的每个人都已经指出,这个问题很可能是由C#应用程序以小端顺序发送INT引起的,而Java应用程序则希望它们以网络顺序(大端顺序)发送INT。然而,正确的方法不是在C#app中显式地重新排列字节,而是依靠内置函数将主机顺序转换为网络顺序(hton等)——这样,即使在big-endian机器上运行,代码也能继续正常工作


一般来说,在对此类问题进行故障排除时,我发现使用netcat或wireshark等工具记录正确的通信量(例如,在您的案例中是Java到Java)非常有用,然后将其与错误的通信量进行比较,看看哪里出了问题。此外,还可以使用netcat将捕获/预记录的请求注入服务器,或将捕获/预记录的响应注入客户端。更不用说,您还可以修改文件中的请求/响应,并在开始修复代码之前测试结果。

Sysetm.Net.IPAddress类有两个静态帮助程序方法:HostToNetworkOrder()和NetworkToHostOrder(),它们为您进行转换。您可以在流上与BinaryWriter一起使用它来写入正确的值:

using (Socket socket = new Socket())
using (NetworkStream stream = new NetworkStream(socket))
using (BinaryWriter writer = new BinaryWriter(stream))
{
    int myValue = 42;
    writer.Write(IPAddress.HostToNetworkOrder(myValue));
}
using (Socket socket = new Socket())
using (NetworkStream stream = new NetworkStream(socket))
using (BinaryWriter writer = new BinaryWriter(stream))
{
    int myValue = 42;
    writer.Write(IPAddress.HostToNetworkOrder(myValue));
}