Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 12.11.2013, 16:13   #1
Atoris
Пользователь
 
Регистрация: 10.10.2010
Сообщений: 32
По умолчанию Сокеты.Сериализация

Клиент и сервер на синхронных сокетах.
Нужно сериализовать данные(объект) и отправить по сокету и десериализовать на стороне клиента. Использую бинарную сериализацию.

Когда размер сериализованных данных маленький - все гладко проходит. Когда он начинает расти, в некоторый момент времени получается так, что приходят на клиент не все данные и десериализация не удается.
Есть идеи? Помогите, товарищи.

Сервер:
Код:
//MailBox => в байты
            byte[] msg = NetworkWorker.Serialize(currentMailBox);
            //размер MailBox
            int mailBoxSize = msg.Length;

            string cmdSize = mailBoxSize.ToString() + NetworkWorker.messageEnd;

            //Отправляем размер
            byte[] msgSize = Encoding.UTF8.GetBytes(cmdSize);
            handler.Send(msgSize);

            //Отправляем Почт ящик
                handler.Send(msg);

byte[] bytes = new byte[NetworkWorker.cmdSize];


            //Ответ от клиента
            int bytesRec = handler.Receive(bytes);
            Console.WriteLine("\nОтвет от клиента: {0}", Encoding.UTF8.GetString(bytes, 0, bytesRec));
Клиент:
Код:
//Получить размер ящика(вычленяем его из строки "размер"+"<THE_END>")
            int mailBoxSize = Convert.ToInt32(NetworkWorker.getCommand(sender));

            //Получить ящик
            serializedMailBox = new byte[mailBoxSize];

                MemoryStream stream = new MemoryStream();
                
                //порция по 2048
                byte[] buf = new byte[NetworkWorker.sendDataSize];

                for (int i = 0; i < mailBoxSize; i = i + NetworkWorker.sendDataSize)
                {
                    //получить порцию
                    sender.Receive(buf);

                    //ReceiveExactly(sender,buf,i,
                    stream.Write(buf, 0, buf.Length);

                }

                stream.Seek(0, 0);
                BinaryFormatter bin = new BinaryFormatter();
                try
                {
                    
                receiveMailBox = (MailBox)bin.Deserialize(stream);
                //receiveMailBox = NetworkWorker.DeSerializeMailBox(serializedMailBox);
                //отобразить в dataGridView
                showOnDataGridView(receiveMailBox.Inbox);
                //Ответ серверу
                byte[] serverCommandBytes =
                    Encoding.UTF8.GetBytes("Почтовый ящик получен!");
                //отправка команды на сервер
                sender.Send(serverCommandBytes);
                }
Код:
public static byte[] Serialize(object Obj)
        {
            BinaryFormatter bin = new BinaryFormatter();
            MemoryStream mem = new MemoryStream();
            bin.Serialize(mem, Obj);
            return mem.GetBuffer();
        }
GetBuffer() - возвращает данные, кратные 2048 байт

Последний раз редактировалось Atoris; 12.11.2013 в 16:17.
Atoris вне форума Ответить с цитированием
Старый 12.11.2013, 16:26   #2
Luuzuk
Форумчанин
 
Аватар для Luuzuk
 
Регистрация: 18.01.2012
Сообщений: 975
По умолчанию

Код ужасен от и до. Предполагаю, что первые грабли выстрелили здесь:
Код:
public static byte[] Serialize(object Obj)
        {
            BinaryFormatter bin = new BinaryFormatter();
            MemoryStream mem = new MemoryStream(); // а освобождать поток кто будет?
            bin.Serialize(mem, Obj);
            return mem.GetBuffer(); // Ага. Весь буфер. С мусором вместо данных в конце. Подразумевалось ToArray() ?
        }
Используйте, если можете, WCF. Оно в тысячу раз надежнее, гибче и удобнее, чем ваш велосипед.
Благодарить в репутацию. Проклинать — туда же
Luuzuk вне форума Ответить с цитированием
Старый 12.11.2013, 16:57   #3
Atoris
Пользователь
 
Регистрация: 10.10.2010
Сообщений: 32
По умолчанию

Цитата:
Сообщение от Luuzuk Посмотреть сообщение
Код ужасен от и до. Предполагаю, что первые грабли выстрелили здесь:
Код:
public static byte[] Serialize(object Obj)
        {
            BinaryFormatter bin = new BinaryFormatter();
            MemoryStream mem = new MemoryStream(); // а освобождать поток кто будет?
            bin.Serialize(mem, Obj);
            return mem.GetBuffer(); // Ага. Весь буфер. С мусором вместо данных в конце. Подразумевалось ToArray() ?
        }
Используйте, если можете, WCF. Оно в тысячу раз надежнее, гибче и удобнее, чем ваш велосипед.
Спасибо! Попробую. А в чем код ужасен? Если можете, по подробней распишите
Atoris вне форума Ответить с цитированием
Старый 12.11.2013, 17:07   #4
Luuzuk
Форумчанин
 
Аватар для Luuzuk
 
Регистрация: 18.01.2012
Сообщений: 975
По умолчанию

Пересылка у вас зачем-то ведется в строковом формате (даже числа, см. mailBoxSize ), причем строки потом конвертируются в массив байт. Не лучше ли будет передавать то же самое число сразу? Хорошей практикой будет использовать BinaryReader / BinaryWriter
Потоки следует использовать в конструкции using, чтобы вовремя освобождать ресурсы

На самом деле, попробуйте WCF
Благодарить в репутацию. Проклинать — туда же
Luuzuk вне форума Ответить с цитированием
Старый 12.11.2013, 17:36   #5
Atoris
Пользователь
 
Регистрация: 10.10.2010
Сообщений: 32
По умолчанию

Цитата:
Сообщение от Luuzuk Посмотреть сообщение
Не лучше ли будет передавать то же самое число сразу?
Каким образом?
Atoris вне форума Ответить с цитированием
Старый 12.11.2013, 18:00   #6
Luuzuk
Форумчанин
 
Аватар для Luuzuk
 
Регистрация: 18.01.2012
Сообщений: 975
По умолчанию

Например через BitConverter
Код:
            Int32 size = 42;
            byte[] a = BitConverter.GetBytes(size);
            Int32 b = BitConverter.ToInt32(a, 0);
Благодарить в репутацию. Проклинать — туда же
Luuzuk вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Сериализация PageControl'а Renok Общие вопросы Delphi 16 12.03.2012 18:55
Сериализация Gregor Компоненты Delphi 10 16.04.2011 12:18
Сериализация Вов@ныч Общие вопросы Delphi 2 06.07.2009 09:54
сериализация Crucian Общие вопросы C/C++ 5 18.11.2007 16:37