none
Метод DataTAble.ReadXml не заполняет таблицу DataTable из XML-данных, передаваемых с TCP-сервера.

    Вопрос

  • Здравствуйте!

    В ответ на запрос клиента TCP-сервер отправляет таблицу в формате XML.

    countriesTable.WriteXml(stream, XmlWriteMode.WriteSchema); //Отправляем таблицу

    На стороне клиента таблица должна восстановиться из XML-данных

    countriesTable.ReadXml(stream);  //Восстанавливаем таблицу

    Здесь countriesTable имеет тип DataTable, stream - NetworkStream.

    Чтобы исключить дополнительные вопросы, поясню. Xml-данные передаются в полном объёме. Я проверял, записывая их в файл. Кроме того, если таблицу восстановить из файла, например:

    countriesTable.ReadXml("xmlFile.xml");

    или из потока MemoryStream, предварительно переписав туда данные, то таблица восстанавливается как надо. Но при попытке заполнить таблицу непосредственно из потока NetworkStream, программа зависает именно на методе ReadXml(stream), никакое исключение при этом не возникает.

    Подскажите, пожалуйста, почему так происходит и можно ли обойтись без лишних операций по переписыванию данных в файл и ли поток MemoryStream?
    14 января 2018 г. 9:41

Ответы

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

    DataTable использует XmlReader для считывания XML из потока. Его конструктор пытается считать из потока определенное количество байт, которое вычисляется методом CalcBufferSize, и зависит от ситуации:

    - для потоков с поддержкой изменения позиции (FileStream/MemoryStream) размер буфера вычисляется хитрым алгоритмом

    - для остальных (NetworkStream) берется жестко заданное значение DefaultBufferSize = 4096

    Для NS нет способа указать конец потока (кроме Socket.Shutdown, но после него сокет не сможет больше слать данные). Поэтому при попытке считать 4КБ, метод Read будет ждать прихода именно этих 4КБ, т.е. на фрагменте <4КБ все повиснет. 

    Вывод - при пересылке XML размером <4КБ нужно действительно, либо делать промежуточный поток с меньшим размером буфера, либо после отправки обязательно закрывать сокет. Как-то так.

    15 января 2018 г. 5:19

Все ответы

  • Попробуйте использовать прокладку в виде BufferedStream.

    This posting is provided "AS IS" with no warranties, and confers no rights.

    14 января 2018 г. 21:02
  • Интересный вопрос. Дело в том, что NetworkStream отличается от других типов потоков довольно значительно, хотя это не всегда очевидно.

    DataTable использует XmlReader для считывания XML из потока. Его конструктор пытается считать из потока определенное количество байт, которое вычисляется методом CalcBufferSize, и зависит от ситуации:

    - для потоков с поддержкой изменения позиции (FileStream/MemoryStream) размер буфера вычисляется хитрым алгоритмом

    - для остальных (NetworkStream) берется жестко заданное значение DefaultBufferSize = 4096

    Для NS нет способа указать конец потока (кроме Socket.Shutdown, но после него сокет не сможет больше слать данные). Поэтому при попытке считать 4КБ, метод Read будет ждать прихода именно этих 4КБ, т.е. на фрагменте <4КБ все повиснет. 

    Вывод - при пересылке XML размером <4КБ нужно действительно, либо делать промежуточный поток с меньшим размером буфера, либо после отправки обязательно закрывать сокет. Как-то так.

    15 января 2018 г. 5:19