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

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

Sending a 4 byte message header from C# client to a Java Server

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

我绝对不熟悉C#,如何将这个消息头发送到Java Server? 我尝试了几种方法(大多数情况下都是反复试验,而又不深入C#语言),但没有任何效果。 Java端的消息长度不正确(很大)。


正如其他张贴者所指出的那样,它是按字节顺序排列的。

Java DataInputStream期望数据为大端(网络字节顺序)。从Mono文档(对于像BinaryWriter这样的对等物)来看,C#倾向于低位优先(Win32 / x86的默认设置)。

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

1
2
3
//byte hex values
Java: 00 00 00 01
  C#: 01 00 00 00

您可以更改在C#中编写int的方式:

1
2
3
4
5
6
7
8
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);
    }
}

编辑:

一种更安全的方法是:

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

正如这里的每个人都已经指出的那样,此问题最有可能是由C#应用程序以低端顺序发送int引起的,而Java应用程序期望它们以网络端(大端顺序)进行发送。但是,与其在C#应用程序中显式重新排列字节,不如正确的方法是依靠内置函数从主机顺序转换为网络顺序(Hton等),这样,即使在运行时,代码也可以继续正常运行在大端机上。

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


很简单,但是您检查了字节序吗?您发送数据的字节序与您接收到的字节序很容易不匹配。


如果您要交换大量数据,我建议您实现(或找到)可以按网络顺序写入和读取整数的Stream-wrapper。但是,如果您真的只需要写长度,请执行以下操作:

1
2
3
4
5
6
7
8
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
}

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

1
2
3
4
5
6
7
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));
}

我不知道C#,但是您只需要做以下等效的事情:

1
2
3
4
out.write((len >>> 24) & 0xFF);
out.write((len >>> 16) & 0xFF);
out.write((len >>>  8) & 0xFF);
out.write((len >>>  0) & 0xFF);


推荐阅读

    linux服务器超时命令?

    linux服务器超时命令?,系统,信息,服务,情况,网站,第一,工作,软件,体系,平均,l

    纯命令行linux服务器?

    纯命令行linux服务器?,密码,服务,系统,命令,终端,地址,百度,情况,状态,公共,

    检查linux服务器命令?

    检查linux服务器命令?,系统,信息,状态,情况,时间,工具,网络,环境,服务,电脑,

    linux同步客户端命令?

    linux同步客户端命令?,时间,网络,服务,系统,认证,状态,管理,信息,分析,地址,l

    linux服务器域名命令?

    linux服务器域名命令?,地址,信息,系统,网络,服务,环境,名称,网站,管理,电脑,l

    linux服务器命令框?

    linux服务器命令框?,系统,情况,状态,信息,数据,软件,指标,服务,在线,工具,lin

    服务器linux命令教程?

    服务器linux命令教程?,系统,地址,密码,网络,设备,工作,服务,标准,连续,管理,

    linux服务器分区命令?

    linux服务器分区命令?,系统,管理,信息,设备,时间,命令,基础,首次,平均,情况,l

    linux服务器上传命令?

    linux服务器上传命令?,服务,软件,平台,数据,工具,系统,手机,电脑,设备,官网,

    linux网络服务器命令?

    linux网络服务器命令?,地址,网络,系统,名称,信息,工具,状态,中心,灵活,基础,l

    linux网络服务器命令?

    linux网络服务器命令?,地址,网络,系统,名称,信息,工具,状态,中心,灵活,基础,l

    linux服务器基本命令?

    linux服务器基本命令?,地址,系统,设备,网络,工作,标准,信息,电脑,命令,密码,l

    linux服务器下载命令?

    linux服务器下载命令?,服务,密码,系统,档案,工具,网络,公共,百度,地址,认证,l

    linux命令测试客户端?

    linux命令测试客户端?,地址,系统,网络,工具,工作,分析,环境,命令,下行,资料,l

    linux服务器常用命令?

    linux服务器常用命令?,工作,系统,地址,信息,命令,目录,管理,标准,设备,功能,

    linux服务器保存命令?

    linux服务器保存命令?,时间,状态,档案,电脑,命令,信息,位置,编辑,文件,模式,L

    linux服务器扫盘命令?

    linux服务器扫盘命令?,地址,工作,命令,目录,数据,单位,名称,系统,管理,信息,L

    linux命令切换服务器?

    linux命令切换服务器?,地址,名称,系统,环境,实时,命令,服务器,脚本,路径,版

    linux服务器搭建命令?

    linux服务器搭建命令?,系统,服务,软件,地址,平台,在线,密码,工具,环境,百度,l

    服务器重启命令linux?

    服务器重启命令linux?,工作,标准,设备,服务,系统,名称,命令,百度,网络,密码,