Десериализация XML из NetworkStream не удалась

У меня есть приложение, настроенное на отправку объектов по сети путем их сериализации в XML на стороне отправки и десериализации на стороне получателя. Сначала я настроил его с помощью UDP, который работал нормально. Код так:

Отправитель:

MemoryStream ms = new MemoryStream();
dataSerializer.Serialize(ms, dataToSend, serNamespaceRemover);
senderClient.Send(ms.GetBuffer(), (int)ms.Length);

Получатель:

IPEndPoint beaconEndpoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), SharedData.udpPort);
byte[] receiveData = beaconClient.Receive(ref beaconEndpoint);
MemoryStream ms = new MemoryStream(receiveData);
CommData recieved = dataDeserializer.Deserialize(ms) as CommData;

Теперь мне нужно переключить его на использование TCP. Отправитель, кажется, работает нормально и впечатляюще прост:

dataSerializer.Serialize(senderClient.GetStream(), dataToSend, serNamespaceRemover);

Но у меня проблемы с приемником. Я попробовал простую и очевидную вещь:

NetworkStream netstr = client.GetStream();
CommData data = dataDeserializer.Deserialize(netstr) as CommData;

И я получаю исключение: в XML-документе есть ошибка (5, 14). XML выглядит так:

<?xml version="1.0"?>
<CommData>
  <RigName>Rig 100</RigName>
  <IsShutDown>false</IsShutDown>
</CommData>

Таким образом, позиция 5,14 — это 2 символа после окончания полученных данных. Я прочитал данные в массив символов и подтвердил, что после конца закрывающей скобки ничего нет, поэтому я не уверен, о чем говорит десериализатор.

Между тем, если я делаю это, то приемник работает:

NetworkStream netstr = client.GetStream();
byte[] arry = new byte[client.Available];
netstr.Read(arry, 0, client.Available);
MemoryStream ms = new MemoryStream(arry);
CommData data = dataDeserializer.Deserialize(ms) as CommData;

Это кажется безумием. Почему он не может просто читать напрямую из NetworkStream? Мне действительно нужно читать данные в MemoryStream, а затем передавать их десериализатору?


person Mason    schedule 08.03.2013    source источник


Ответы (2)


См.: Десериализация данных, отправляемых через TCP

Ответ предполагает, что NetworkStream не будет уведомлять, когда будет прочитан последний байт. Таким образом, кажется, что ваш десерлиализатор продолжает пытаться читать (даже после достижения конца, потому что NetworkStream не уведомляет об этом) из NetworkStream и, следовательно, приводит к исключению. Вам нужно будет прочитать в MemoryStream.

person publicgk    schedule 08.03.2013
comment
Хороший улов, я сам думал в том же направлении. Спас меня от некоторых исследований, и я узнал кое-что новое :) - person Nevyn; 09.03.2013
comment
NetworkStream.DataAvailable что-то близкое но не думаю, что это поможет в вашем сценарии. - person publicgk; 09.03.2013

Как узнать, что вы получили весь файл XML? Пока удаленный конец не закрыл соединение, вызов Read (который будет выполнять XmlSerializer) будет блокироваться и ждать данных.

person Guvante    schedule 08.03.2013
comment
У меня действительно была эта проблема раньше, но в этом случае это не блокировка, а скорее чтение чего-то недействительного и создание исключения. - person Mason; 09.03.2013