Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# .NET
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.56/18: Рейтинг темы: голосов - 18, средняя оценка - 4.56
mr_black
0 / 0 / 0
Регистрация: 18.06.2009
Сообщений: 7
#1

XML сериализация в сетевой поток

18.06.2009, 10:25. Просмотров 3306. Ответов 12
Метки нет (Все метки)

Есть непонятная проблема с десериализацией из сетевого потока. На клиентской стороне происходит сериализация класса с данными в сетевой поток. На стороне сервера при подключении клиента открывается поток чтения данных с клиента:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
private void DoClient()
        {
            string clientadr;
            TcpClient client = tcpListener.AcceptTcpClient();
            clientadr = client.Client.RemoteEndPoint.ToString();
            Packet d = new Packet();
            XmlSerializer serializer = new XmlSerializer(typeof(Packet));
            //NetworkStream clientstrm = client.GetStream();
            while (!StopThread)
            {
                Thread.Sleep(10);
                if (client.Available > 0)
                {
                    NetworkStream clientstrm = client.GetStream();
                    d = (Packet)serializer.Deserialize(clientstrm);
                    SaveXMLObj(d, clientadr);
                }
            }
На строке десериализации программа останавливается. Если следом приходит следующий пакет возникает эксепшен (ошибка в XML). Нормально продолжается только в случае закрытия соединения клиентом, что недопустимо т.к. предпологается двухсторонний обмен данными с клиентом в течении продолжительного времени. Вариант когда из потока чтение делается в массив байт с последующим его преобразованием в поток памяти (memory stream) и десериализацией работает нормально.

Что с сетевым потоком не так?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.06.2009, 10:25
Ответы с готовыми решениями:

Сериализация в xml
Имеется несколько классов следующего вида (схематично): public class A { ...

XML сериализация
Добрый день! 1. Как при сериализации XmlSerializer xmlSerializer = new...

Сериализация в Xml в С#
Доброе всем время суток! Нужна помощь по сериализации. Есть несколько...

XML сериализация списка
По какой схеме нужно сериализовать однонаправленный упорядоченный список?...

XML Сериализация. Ошибка
Пытаюсь сериализировать - Фиг Необработанное исключение типа...

12
exe-dealer
302 / 155 / 11
Регистрация: 07.06.2009
Сообщений: 538
18.06.2009, 14:32 #2
может ему Seek() нужен для десериализации
0
mr_black
0 / 0 / 0
Регистрация: 18.06.2009
Сообщений: 7
18.06.2009, 14:40  [ТС] #3
У сетевого потока, по сути, нет метода Seek(), как и свойств Position, Length, CanSeek всегда false.
0
exe-dealer
302 / 155 / 11
Регистрация: 07.06.2009
Сообщений: 538
18.06.2009, 14:50 #4
вот может в этом и дело, может для десериализации нужен Seek, а его нет
0
mr_black
0 / 0 / 0
Регистрация: 18.06.2009
Сообщений: 7
18.06.2009, 15:01  [ТС] #5
В MSDN ничего не упоминается об каких либо ограничениях...

---
public Object Deserialize( Stream stream)

Use the stream parameter to specify an object that derives from the Stream class, which is designed to write to streams. Classes that derive from the Stream class include:

BufferedStream
FileStream
MemoryStream
NetworkStream
CryptoStream
---
0
exe-dealer
302 / 155 / 11
Регистрация: 07.06.2009
Сообщений: 538
18.06.2009, 15:14 #6
пусть тогда клиент пошлет после сериализованого класа пару переводов строк, может поможет.

зы кстате
>Packet d = new Packet();
это незачем вроде бы, у вас потом затирается же сылка на новый объект новым десериалтзованым
0
mr_black
0 / 0 / 0
Регистрация: 18.06.2009
Сообщений: 7
18.06.2009, 15:49  [ТС] #7
Цитата Сообщение от exe-dealer Посмотреть сообщение
пусть тогда клиент пошлет после сериализованого класа пару переводов строк, может поможет.

зы кстате
>Packet d = new Packet();
это незачем вроде бы, у вас потом затирается же сылка на новый объект новым десериалтзованым
Переводы строк не помогли

Packet в = new Packet();
создает экземпляр класса, в который и должен поместиться десериализованный класс...

Добавлено через 16 минут 21 секунду
Может эксепшен кого наведет на мысли...

System.InvalidOperationException was unhandled
Message="В документе XML (10, 3) присутствует ошибка."
Source="System.Xml"
StackTrace:
в System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
в System.Xml.Serialization.XmlSerializer.Deserialize(Stream stream)
в XMLServer.Form1.DoClient() в C:\Work\Visual Studio 2008\Projects\XMLServer\XMLServer\Form1.cs:строка 99
в System.Threading.ThreadHelper.ThreadStart_Context(Object state)
в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
в System.Threading.ThreadHelper.ThreadStart()
InnerException: System.IO.IOException
Message="Не удается прочитать данные из транспортного соединения: Попытка установить соединение была безуспешной, т.к. от другого компьютера за требуемое время не получен нужный отклик, или было разорвано уже установленное соединение из-за неверного отклика уже подключенного компьютера."
Source="System"
StackTrace:
в System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
в System.Xml.XmlTextReaderImpl.ReadData()
в System.Xml.XmlTextReaderImpl.ParseDocumentContent()
в System.Xml.XmlTextReaderImpl.Read()
в System.Xml.XmlTextReader.Read()
в System.Xml.XmlReader.ReadEndElement()
в System.Xml.Serialization.XmlSerializationReader.ReadEndElement()
в Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderPacket.Read2_Packet(Boolean isNullable, Boolean checkType)
в Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderPacket.Read3_Request()
InnerException: System.Net.Sockets.SocketException
Message="Попытка установить соединение была безуспешной, т.к. от другого компьютера за требуемое время не получен нужный отклик, или было разорвано уже установленное соединение из-за неверного отклика уже подключенного компьютера"
Source="System"
ErrorCode=10060
NativeErrorCode=10060
StackTrace:
в System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
в System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
InnerException:
0
exe-dealer
302 / 155 / 11
Регистрация: 07.06.2009
Сообщений: 538
18.06.2009, 15:52 #8
а , блин так у вас эксепшн, а я вскользь прочел и подумал что поток засыпает на десериализации.
дайте глянуть на этот xml код который в поток шлется.
0
mr_black
0 / 0 / 0
Регистрация: 18.06.2009
Сообщений: 7
18.06.2009, 16:29  [ТС] #9
Цитата Сообщение от exe-dealer Посмотреть сообщение
а , блин так у вас эксепшн, а я вскользь прочел и подумал что поток засыпает на десериализации.
дайте глянуть на этот xml код который в поток шлется.
ээээээ
не совсем так.
Если после передачи клиент закрывает сокет, то никакого эксепшена и зависания не происходит - все работает без проблем. Эксепшен появляется если клиент после первой посылки, отсылает вторую или если на стороне сервера сделать clientstrm.ReadTimeout = 100; т.е. задать тайм-айт на чтение из потока. Складывается такое впечатление, что метод Deserialize читает синхронным методом Read из потока, при этом задает большой размер буффера чтения и ждет пока заполнится буффер. Но когда буффер заполняется, то там уже не один класс данных лежит, а несколько. Вот он и вылетает в эксепшен....

А отсылается с клиента XML которые получен из класса сериализатором, ничего больше не прибавляется.
0
Green
1919 / 424 / 40
Регистрация: 12.07.2007
Сообщений: 2,062
Завершенные тесты: 2
19.06.2009, 04:33 #10
Десериализатор вычитывает весь поток и весь пытается привести к экземпляру указанного типа. Нужно вычитывать необходимый размер и полученный буфер отдавать десериализатору, так как вы указали с MemoryStream.
Кстати, почему используете XmlSerializator, для передачи по сети выгоднее BinaryFormatter.
0
mr_black
0 / 0 / 0
Регистрация: 18.06.2009
Сообщений: 7
19.06.2009, 10:23  [ТС] #11
Цитата Сообщение от Green Посмотреть сообщение
Десериализатор вычитывает весь поток и весь пытается привести к экземпляру указанного типа. Нужно вычитывать необходимый размер и полученный буфер отдавать десериализатору, так как вы указали с MemoryStream.
Кстати, почему используете XmlSerializator, для передачи по сети выгоднее BinaryFormatter.
Откуда информация, что десериализатор вычитывает ВЕСЬ поток? В MSDN об этом ничего не сказано... Мне думалось, что десериализатор читает поток и по-ходу парсит его пока не встретит закрытие корневого тэга. Иначе смысла в связке десеарилизатор и сетевой поток вообще нет. А если делать через буффер в памяти, то воникает проблема как контролировать, что в буффер из сетевого потока вычитан один экземпляр передаваемого класса, а не 0,5 или 1,5....
Хоть свой парсер пиши....

Добавлено через 6 минут 18 секунд
XMLSerializator используется по причине отсутсвия предачи больших объемов информации. Передаватся будут команды управления. И для того, что бы протокол сделать открытым. Клиенты будут писаться на разных платформах.
0
Green
1919 / 424 / 40
Регистрация: 12.07.2007
Сообщений: 2,062
Завершенные тесты: 2
19.06.2009, 11:59 #12
Согласно спецификации XML возможен только один корневой элемент. Получается если поток не закрыть и добавить еще xml-кода, то происходит нарушение стандарта. Для xml это неприемлимо.
Придется вводить контроль. Примерно: взвешивать весь xml-текст одного экземпляра и полученную длину подавать перед посылкой текста. Вычитывать сначала длину, а по ней вычитывать текст.
1
mr_black
0 / 0 / 0
Регистрация: 18.06.2009
Сообщений: 7
19.06.2009, 13:47  [ТС] #13
Цитата Сообщение от Green Посмотреть сообщение
Согласно спецификации XML возможен только один корневой элемент. Получается если поток не закрыть и добавить еще xml-кода, то происходит нарушение стандарта. Для xml это неприемлимо.
Придется вводить контроль. Примерно: взвешивать весь xml-текст одного экземпляра и полученную длину подавать перед посылкой текста. Вычитывать сначала длину, а по ней вычитывать текст.
Спасибо за совет! Я это еще с самого начала продумывал и пришел к выводу, что майкрософтовцы как раз это и сделали в своем десереализаторе, но видиммо ошибся
0
19.06.2009, 13:47
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.06.2009, 13:47

(Де)сериализация разных типов из XML
Доброго времени, форумчане! Помогите, пожалуйста, с...

Сериализация/Десериализация списка объектов в XML
имеется базовый класс Figure using System; using System.Collections.Generic;...

Сериализация или парсить xml? (хранение настроек приложения)
Всем привет! Подскажите, как правильно хранить настройки? Можно: Написать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru