Буфер С# BinaryWriter для отправки сегментов?

Я не уверен, что «буфер» — это то, что я ищу, поэтому я покажу вам свою проблему, а затем вы, ребята, сможете решить, правильное ли это слово и какое решение. В настоящее время я работаю над созданием сетевого порта для класса Java DataOutputStream в C#. Последнее, что мне нужно сделать, это решить эту проблему с отправкой сегментированной информации.

Вот мой метод WriteInt на C# (ClientOutput является экземпляром BinaryWriter)

public void WriteInt(int v)
{
    ClientOutput.Write (((uint)v >> 24) & 0xFF);
    ClientOutput.Write (((uint)v >> 16) & 0xFF);
    ClientOutput.Write (((uint)v >> 8) & 0xFF);
    ClientOutput.Write (((uint)v >> 0) & 0xFF);
    IncCount (4);
}

Для тех, кто хочет сравнить; вот оригинал на Java

public final void writeInt(int v) throws IOException {
       out.write((v >>> 24) & 0xFF);
       out.write((v >>> 16) & 0xFF);
       out.write((v >>>  8) & 0xFF);
       out.write((v >>>  0) & 0xFF);
       incCount(4);
}

Обычно в java вам нужно будет вызывать "Flush()" до того, как данные будут отправлены на сервер или клиент; Однако оказывается, что BinaryWriter автоматически сбрасывается всякий раз, когда вы вызываете «Write()».

Вот код "ReadInt()" на Java.

public final int readInt() throws IOException {
        int ch1 = in.read();
        int ch2 = in.read();
        int ch3 = in.read();
        int ch4 = in.read();
        if ((ch1 | ch2 | ch3 | ch4) < 0)
            throw new EOFException();
        return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}

Когда код Java выполняется для "WriteInt" и ReadInt вызывается на сервере, значение отображается правильно; Однако в настоящее время сервер обрабатывает целое число 4 раза и отображает целочисленное значение на основе сегментов.

Пример ввода (C#):

Client.WriteInt(1000);

Пример вывода (Java):

0
0
50331648
-402653184

Когда вывод должен быть:

1000

Пожалуйста, потерпите меня, так как я только что взял C # несколько дней назад и, возможно, задаю глупый вопрос.


person Hobbyist    schedule 16.10.2014    source источник


Ответы (1)


BinaryWriter имеет кучу перегрузок метода Write(), и похоже, что вы вызываете перегрузку Write(Int32), которая, конечно же, отправляет четыре 4-байтовых целых числа.

Вы должны иметь возможность решить проблему, просто переведя значения в байты при вызове Write():

public void WriteInt(int v)
{
    ClientOutput.Write ((byte)(((uint)v >> 24) & 0xFF));
    ClientOutput.Write ((byte)(((uint)v >> 16) & 0xFF));
    ClientOutput.Write ((byte)(((uint)v >> 8) & 0xFF));
    ClientOutput.Write ((byte)(((uint)v >> 0) & 0xFF));
    IncCount (4);
}

Обратите внимание, что с технической точки зрения вам не нужно приводить значение v к uint перед сдвигом. Даже если произойдет расширение знака, вы все равно маскируете все, кроме последнего байта. Но эта часть не должна ничего повредить.

Ознакомьтесь с версией BinaryWriter Джона Скита, поддерживающей порядок байтов. Здесь есть обсуждение и несколько ссылок: BinaryWriter Endian issue

person Peter Duniho    schedule 16.10.2014
comment
Единственная причина, по которой я использовал uint, заключалась в том, что исходная библиотека, написанная на java, использовала сдвиги без знака. Я решил, что для этого есть причина, поэтому я сохранил их методы. Я попробую это, как только вернусь домой, и посмотрю, работает ли это. - person Hobbyist; 16.10.2014
comment
Работает отлично, СПАСИБО! - person Hobbyist; 16.10.2014