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

7

我正在尝试编写一个C#客户端与Java编写的服务器通信。该服务器期望收到一个4字节(Java中的DataInputStread readInt())的消息头,然后是实际的消息内容。

我对C#完全不熟悉,如何将此消息头发送到Java服务器?我尝试了几种方式(大多数是尝试和错误,没有深入研究C#语言),但都没有成功。Java端最终收到了不正确的(非常大的)消息长度。

6个回答

11

正如其他帖子所指出的那样,这取决于字节序。

Java DataInputStream 期望数据为big-endian(网络字节顺序)。从Mono文档中可以看出(例如BinaryWriter的等效类),C# 倾向于采用小端序(Win32/x86 的默认值)。

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

//byte hex values
Java: 00 00 00 01
  C#: 01 00 00 00

你可以改变在C#中编写整数的方式:

private static void WriteInt(Stream stream, int n) {
    for(int i=3; i>=0; i--)
    {
        int shift = i * 8; //bits to shift
        byte b = (byte) (n >> shift);
        stream.WriteByte(b);
    }
}

编辑:

更安全的做法是:

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

2

这很简单,但你是否检查了字节序?发送数据时使用的字节序与接收数据时使用的字节序可能不匹配。


2
正如这里的每个人已经指出的那样,问题很可能是由于C#应用程序以小端顺序发送整数,而Java应用程序期望它们以网络顺序(大端)发送所引起的。然而,正确的方法不是在C#应用程序中显式地重新排列字节,而是依赖于内置函数来进行从主机到网络顺序的转换(如htons等)-- 这样你的代码即使在大端机器上运行时也会继续正常工作。
通常,在解决此类问题时,我发现使用netcat或wireshark等工具记录正确的流量(例如,在您的情况下是从Java到Java),然后将其与不正确的流量进行比较,以确定出错的地方是非常有用的。作为额外的好处,您还可以使用netcat将捕获/预录制的请求注入服务器或将捕获/预录制的响应注入客户端。更不用说,您还可以修改文件中的请求/响应并测试结果,然后再开始修复代码。

1
如果你要交换大量数据,我建议实现(或查找)一个可以按网络顺序写入和读取整数的流包装器。但是如果你只需要写入长度,请像这样操作:
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
}

0

我不懂C#,但你只需要做相当于这个的事情:

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

0

System.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));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接