XmlSerializer.Deserialize блокирует через NetworkStream - PullRequest
4 голосов
/ 29 апреля 2010

Я пытаюсь отправить сериализуемые объекты XML через сетевой поток.

Я уже использовал это на широковещательном сервере UDP, где он получает UDP-сообщения из локальной сети. Вот фрагмент серверной части:

while (mServiceStopFlag == false) {
    if (mSocket.Available > 0) {
        IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, DiscoveryPort);       byte[] bData;

    // Receive discovery message
    bData = mSocket.Receive(ref ipEndPoint);
    // Handle discovery message
    HandleDiscoveryMessage(ipEndPoint.Address, bData);
    ...

Вместо этого это сторона клиента:

IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Broadcast, DiscoveryPort);
MemoryStream mStream = new MemoryStream();
byte[] bData;

// Create broadcast UDP server
mSocket = new UdpClient();
mSocket.EnableBroadcast = true;

// Create datagram data
foreach (NetService s in ctx.Services)
    XmlHelper.SerializeClass<NetService>(mStream, s);
bData = mStream.GetBuffer();

// Notify the services
while (mServiceStopFlag == false) {
    mSocket.Send(bData, (int)mStream.Length, ipEndPoint);
    Thread.Sleep(DefaultServiceLatency);
}

Работает очень хорошо.

Но теперь я пытаюсь получить тот же результат, но на сокете TcpClient, но используя непосредственно экземпляр XMLSerializer:

На стороне сервера:

    TcpClient sSocket = k.Key;
ServiceContext sContext = k.Value;
Message msg = new Message();

while (sSocket.Connected == true) {
    if (sSocket.Available > 0) {
        StreamReader tr = new StreamReader(sSocket.GetStream());
        msg = (Message)mXmlSerialize.Deserialize(tr);

        // Handle message
        msg = sContext.Handler(msg);
        // Reply with another message
        if (msg != null)
            mXmlSerialize.Serialize(sSocket.GetStream(), msg);
    } else
        Thread.Sleep(40);
}

А на стороне клиента:

NetworkStream mSocketStream;
Message rMessage;

// Network stream
mSocketStream = mSocket.GetStream();

// Send the message
mXmlSerialize.Serialize(mSocketStream, msg);
// Receive the answer
rMessage = (Message)mXmlSerialize.Deserialize(mSocketStream);

return (rMessage);

Данные отправляются (доступное свойство больше 0), но метод XmlSerialize.Deserialize (который должен десериализовать класс Message) блокирует.

Чего мне не хватает?

1 Ответ

2 голосов
/ 03 мая 2010

Конечно, потому что сериализатор продолжает читать NetworkStream, и он не заканчивается, когда появляется основной конечный элемент.

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

...