2014-02-14 5 views
0

В настоящее время я использую клиент C# для моего сервера C++. Протокол связи двоичный. На стороне сервера нет проблем, поскольку двоичная сериализация - это всего лишь вопрос memcpy. Однако у моего клиента C# есть проблемы с отправкой данных через сокеты.Двоичная сериализация на сокетах

Прежде всего, здесь мои структуры данных:

Заголовок:

[Serializable] 
public class Header 
{ 
    public UInt32 UserId { get; set; } 
    public UInt16 CheckSum { get; set; } 
    public byte Status { get; set; } 
    public byte Command { get; set; } 
    public byte Device { get; set; } 
    public byte Method { get; set; } 
    public byte KeepAlive { get; set; } 
    public byte Osef { get; set; } 
    public Header() 
    { 
     UserId = 0; 
     CheckSum = 0; 
     Status = 0; 
     Command = 0; 
     Device = 0; 
     Method = 0; 
     KeepAlive = 0; 
     Osef = 0; 
    } 
    public static UInt16 Size() 
    { 
      return Convert.ToUInt16(sizeof(byte) * 6 + sizeof(UInt32) + sizeof(UInt16)); 
    } 

    internal void write(Stream stream) 
    { 
     BinaryWriter writer = new BinaryWriter(stream); 

     writer.Write(UserId); 
     writer.Write(CheckSum); 
     writer.Write(Status); 
     writer.Write(Command); 
     writer.Write(Device); 
     writer.Write(Method); 
     writer.Write(KeepAlive); 
     writer.Write(0); //alignement 
    } 

    internal void read(Stream stream) 
    { 
     BinaryReader reader = new BinaryReader(stream); 

     UserId = reader.ReadUInt32(); 
     CheckSum = reader.ReadUInt16(); 
     Status = reader.ReadByte(); 
     Command = reader.ReadByte(); 
     Device = reader.ReadByte(); 
     Method = reader.ReadByte(); 
     KeepAlive = reader.ReadByte(); 
     reader.ReadByte(); //alignement 
    } 
} 

Структура данных с заголовком первого:

[Serializable] 
class UserPass 
{ 
    public Header Header { get; set; } 
    public UInt16 User_checkSum { get; set; } 
    public byte[] Username { get; set; } 
    public UInt16 Pass_checkSum { get; set; } 
    public byte[] Password { get; set; } 

    public UInt16 Size() 
    { 
     return Convert.ToUInt16((sizeof(byte) * 128) + (sizeof(byte) * 128) + sizeof(UInt16) * 2); 
    } 

    public UserPass() 
    { 
     Header = new Header(); 
     User_checkSum = 0; 
     Username = new byte[128]; 
     Pass_checkSum = 0; 
     Password = new byte[128]; 
    } 

    internal void write(Stream stream) 
    { 
     BinaryWriter writer = new BinaryWriter(stream); 

     Header.write(stream); 
     writer.Write(User_checkSum); 
     writer.Write(Username, 0, 128); 
     writer.Write(Pass_checkSum); 
     writer.Write(Password, 0, 128); 
    } 

    internal void read(Stream stream) 
    { 
     BinaryReader reader = new BinaryReader(stream); 

     Header.read(stream); 
     User_checkSum = reader.ReadUInt16(); 
     Username = reader.ReadBytes(User_checkSum); 
     Pass_checkSum = reader.ReadUInt16(); 
     Password = reader.ReadBytes(Pass_checkSum); 
    } 
} 

я пишу мои данные, используя записи функции Header и UserPass и передачу NetworkStream в качестве аргумента, который я преобразовал из своего сокета с GetStream.

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

  • Я попытался использовать тот же объект BinaryWriter для обоих. Не разрешил.

  • Я пробовал с промывкой струей. Не разрешил (а)

  • Я пробовал некоторые причудливые библиотеки и библиотеку protobuf-net. Это сделало еще хуже, заголовок был полон тарабарщины.

Что интересно, когда я пытаюсь сериализация этих структур в файл, используя те же методы, что либо библиотека или методы записи структур, он отлично работает, данные, хранящиеся в файле правильный, но когда я отправляю его через сокет, он терпит неудачу.

+0

Ошибка на стороне чтения, пожалуйста, укажите код десериализации C++. –

+0

читая контрольную сумму и рассматривая это как длину, звучит немного ... нечетно; вы уверены, что используете это право? Я должен сказать, однако: я делаю * много * программирования 'Stream' и' Socket'. Количество раз, когда я использую 'BinaryReader' /' BinaryWriter': ноль. Это просто не полезно для большинства протоколов. –

+0

О, и в самом деле: protobuf-net не поможет, если фактический протокол здесь protobuf, что я сомневаюсь. У вас есть определение фактического протокола? –

ответ

0

В принципе, ваш «выравнивание» записывает int вместо байта.

в классе Header пишут() метод, изменение ...

writer.Write(0); //alignement 

... до ...

writer.Write((byte)0); //alignement 

Тогда ваш Read, кажется, работает хорошо, и любой другой вопрос с чтением сообщений или на стороне сервера.

+0

Спасибо, что было пятно на! Я действительно чувствую себя глупо сейчас ... – 6MarViN

Смежные вопросы