Ошибка десериализации - C # - PullRequest
1 голос
/ 31 марта 2010

Я написал некоторый код, который представляет собой миниатюрную имитацию программы обмена сообщениями. В программе; когда пользователь выходит из системы, экземпляр моего класса LogOutCommand подготавливается клиентской программой, сериализуется и отправляется на сервер. Когда сервер получает LogOutCommand, он десериализует и вызывает метод Execute класса, который выполняет операции с БД и т. Д.

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

Как я могу заставить сервер начать десериализацию так, чтобы он ожидал завершения отправки всех связанных байтов?

Или вы думаете, что есть другая проблема?

Вот код:

// Сервер прослушивает сокет

    private void ReadData(object obj)
    {
        Socket client = (Socket)obj;

        while (true)
        {
            if (client.Available > 0)
            {
                byte[] buffer = new byte[client.Available];
                client.Receive(buffer);
                ServerCommandBase cmd = CommandReader.ReadSrvCommand(buffer);
                cmd.Execute(context);

            }
        }
    }

// Класс CommandReader

public class CommandReader
{
    public static ServerCommandBase ReadSrvCommand(byte[] buffer)
    {
        return (ServerCommandBase)SerializationUtility.SerializationHelper.Deserialize(buffer);
    }
    public static ClientCommandBase ReadCliCommand(byte[] buffer)
    {
        return (ClientCommandBase)SerializationUtility.SerializationHelper.Deserialize(buffer);
    }

}

// Класс сериализации / десериализации

открытый класс SerializationHelper { public static byte [] Serialize (объектный объект) { BinaryFormatter formatter = new BinaryFormatter (); MemoryStream stream = new MemoryStream (); пытаться { formatter.Serialize (stream, obj); } поймать (исключение) { MessageBox.Show («Сериализация Эдилемиор»); }
stream.Position = 0; возвратный поток. ToArray (); }

    public static object Deserialize(byte[] byteArr)
    {
        BinaryFormatter formatter = new BinaryFormatter();
        MemoryStream ms = new MemoryStream(byteArr);
        ms.Position = 0;
        object retObj = null;
        try
        {
            retObj = formatter.Deserialize(ms);
        }
        catch (Exception)
        {
            MessageBox.Show("Cannot Be Deserialized!");
        }

        return retObj;
    }




}

Ответы [ 2 ]

1 голос
/ 31 марта 2010

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

Вам следует отправить заголовок с вашим сообщением, в котором указывается, как долго (в байтах) будут данные. Затем вы берете байты до тех пор, пока это число не будет достигнуто, и десериализуетесь тогда и только тогда.

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

0 голосов
/ 31 марта 2010

Прежде всего, вы не должны использовать BinaryFormatter. Гораздо лучше использовать, например XmlSerializer.

Во-вторых, пожалуйста, включите информацию об исключении, которое вы получите.

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