从C#客户端向Java服务器发送一个4字节的消息头
我正在尝试将一个C#客户机写入一个用Java编写的服务器。服务器需要一个4字节(Java中的DataInputStread readInt())的消息头,后跟实际消息从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服务器?我尝试了几种方法(大多是反复尝试,没有深入到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));
}