【问题标题】:Reading and writing data between c# and java sockets在 c# 和 java 套接字之间读取和写入数据
【发布时间】:2012-01-19 13:09:54
【问题描述】:

我整天都在和这个作斗争。我需要在 C# 服务器和 Java 客户端之间发送字符串 (JSON)。我必须将前 4 个字节(总是 4 个字节)作为消息的长度(标题,所以我们知道消息的其余部分有多长),然后是消息的正文。流在应用程序的生命周期内保持打开状态。就我个人而言,我会用“\n”分隔每条消息,然后使用 readLine(),但客户端需要这种方式。

我需要 C# 端以及 Java 端来发送和接收这些消息。不太清楚如何编码和解码所有内容。

我一直在玩的一些位:

C# 发送

byte[] body = Encoding.ASCII.GetBytes(message);
byte[] header = BitConverter.GetBytes((long) body.Length);

foreach (byte t in header)
{
    networkStream.WriteByte(t);
}


foreach (byte t in body)
{
    networkStream.WriteByte(t);
}

我还没有到 C# 接收。 Java 发送:

byte[] dataToSend = data.getBytes();
byte[] header = ByteBuffer.allocate(4).putInt(dataToSend.length).array();
ByteArrayOutputStream output = new ByteArrayOutputStream();
output.write(header);
output.write(dataToSend);
output.writeTo(outputStream);

Java 接收:

byte[] header = new byte[4];
int bytesRead;
do {
    Debug.log("TCPClient- waiting for header...");
    bytesRead = reader.read(header);

    ByteBuffer bb = ByteBuffer.wrap(header);
    int messageLength = bb.getInt();

    Debug.log("TCPClient- header read. message length (" + messageLength + ")");

    byte[] body = new byte[messageLength];
    do {
       bytesRead = reader.read(body);
    }
    while (reader.available() > 0 && bytesRead != -1);
}
while (reader.available() > 0 && bytesRead != -1);

我知道代码并不完整,但谁能提供任何帮助?

【问题讨论】:

  • 我会在 C# 上使用 TextReader 和 StreamWriter。更容易,您可以直接使用字符串写入和读取消息。
  • 正如我所说,我别无选择。我必须发送前 4 个字节作为消息的长度。

标签: c# java string sockets bytearray


【解决方案1】:

'\n' 分隔消息不是一个好主意,除非您确定您的消息将仅包含单行文本。如果 '\n' 在您的一条消息中固有地出现,那么该消息将被拆分。

您声明消息长度必须恰好是 4 个字节;但是,以下行会生成一个 8 字节数组:

byte[] header = BitConverter.GetBytes((long) body.Length);

原因是,在 C# 中,longInt64 结构的别名,表示 64 位有符号整数。您需要的是一个intuint,它代表一个32 位有符号或无符号整数。因此,只需将上面的行更改为:

byte[] header = BitConverter.GetBytes(body.Length);

您需要考虑的另一个重要因素是数据的endianness。想象一下,你正试图为一个值创建一个 4 字节数组,比如 7。在大端平台上,这将被编码为 0,0,0,7;在 little-endian 平台上,它将被编码为 7,0,0,0。但是,如果在具有反向字节序的平台上对其进行解码,7 将被解释为最高有效字节,其值为 117,440,512(等于 7×2563)而不是 7 .

因此,Java 和 C# 应用程序的字节序必须相同。 Java ByteBuffer 默认为大端;但是,C# BitConverter 依赖于体系结构,可以通过其 IsLittleEndian 静态属性进行检查。您可以通过在数组为小端时反转数组来让 C# 始终遵循大端约定:

byte[] header = BitConverter.GetBytes(body.Length);
if (BitConverter.IsLittleEndian)
    Array.Reverse(header);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-22
    • 2022-01-25
    • 1970-01-01
    • 2020-08-21
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多