【问题标题】:C# server and Java client TCPC# 服务器和 Java 客户端 TCP
【发布时间】:2019-02-26 09:21:32
【问题描述】:

问题是GetBufferSize 方法,我发送一个大小为 40 的缓冲区,它返回一个奇怪的数字 54124。
为什么java int byte code和C# int byte code不一样?

JAVA 客户端

mBufferOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), UTF8)), true);

private void sendMessage(final String message) {

    if (mBufferOut != null && message != null) {
        try {
            Log.d("_TAG", "Message length: " + Integer.toString(message.length()));

            Log.d("_TAG", "Sending: " + message);
            mBufferOut.print(message.length());
            mBufferOut.flush();
            mBufferOut.print(message);
            mBufferOut.flush();
        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }
}

上面的代码发送了两条消息:第一个是缓冲区大小,第二个是数据本身。

C# 服务器

private void Read() {
    int size = GetBufferSize();

    byte[] myReadBuffer = new byte[size];
    int numberOfBytesRead = 0;
    string str = "";

    do
    {
        numberOfBytesRead = networkStream.Read(myReadBuffer, 0, myReadBuffer.Length);

        str = Encoding.UTF8.GetString(myReadBuffer, 0, numberOfBytesRead);
    } while (networkStream.DataAvailable);
}

private int GetBufferSize()
{
    byte[] myReadBuffer = new byte[4];
    int numberOfBytesRead = 0;

    do
    {
        numberOfBytesRead = networkStream.Read(myReadBuffer, 0, myReadBuffer.Length);
    } while (networkStream.DataAvailable);

    if (numberOfBytesRead > 0)
    {
        return BitConverter.ToInt32(myReadBuffer, 0);
    }
    else
    {
        return 0;
    }
}

有什么想法吗?

【问题讨论】:

  • 我建议您将发送的字节和接收的字节视为单独的字节。检查它们是否相同。弄清楚它们如何代表您发送的人类可读的值。弄清楚它们如何代表您收到的错误值。

标签: java c# tcp


【解决方案1】:

解决方案

         `return   Int32.Parse(Encoding.UTF8.GetString(myReadBuffer, 0, myReadBuffer.Length))`;

问题

公共无效打印(int inum)

将指定整数的字符串表示形式打印到 目标。

Integer 被转换为该 int 的字符串表示形式,然后转换为字节。

【讨论】:

  • 当然正确的解决方案是将值作为字节发送?
  • 好的,但是 PrintWriter 不允许发送字节,或者是它,我检查了它没有可用的方法,它们都采用其他数据类型
  • 我不熟悉Java,但是:我认为您的问题源于使用文本编码来发送数据。我想getOutputStream() 返回的流能够写入字节。你用OutputStreamWriter 包装它,根据文档,它是从字符流到字节流的桥梁。这取决于你真的想投入多少工作。您也可以只发送“长度,消息”,然后GetBufferSize() 可以一直读取到逗号,然后从逗号前字符串中解析出长度。
  • 我对Java也不熟悉,我发现你可以用binaryformatter对其进行变形并直接写入字节。
【解决方案2】:

您可能遇到了有关字节序的问题。 Java 以大端存储数据,而 .NET 根据您的系统架构存储数据。如果您使用的是 x86 机器,则很可能您正在尝试读取 big-endian 数据,就好像它是 little-endian 一样。您必须在读取之前反转字节数组

            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(buffer);
            }

Here's more info in endianness.

【讨论】:

  • 其实Oracle JVM 和Microsoft CLR 存储数据的方式是一样的,都是系统依赖的。他们将数据写入流的方式可能不同。
  • 35 缓冲区大小变成 859111424 ,我添加了您的代码不起作用
  • android设备是VM,Windows应用是x86
  • @vandench JVM 内部的数据存储取决于系统架构。但是,存储在 JVM 上运行的程序中的任何多字节数据项都是大端的。 See page 69 of this book
猜你喜欢
  • 1970-01-01
  • 2019-02-26
  • 1970-01-01
  • 2012-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-09
  • 2023-03-21
相关资源
最近更新 更多