Я пытаюсь разобрать XML-сообщения, которые отправляются на мое приложение С# через TCP. К сожалению, протокол не может быть изменен, а XML-сообщения не разделены и префикс длины не используется. Кроме того, кодировка символов не является фиксированной, но каждое сообщение начинается с объявления XML <?xml>. Вопрос в том, как я могу читать одно XML-сообщение за раз, используя С#.
До сих пор я пытался прочитать данные из потока TCP в массив байтов и использовать его через MemoryStream. Проблема в том, что буфер может содержать более одного XML-сообщения или первое сообщение может быть неполным. В этих случаях я получаю исключение при попытке проанализировать его с помощью XmlReader.Read или XmlDocument.Load, но, к сожалению, XmlException не позволяет мне отличать проблему (кроме синтаксического анализа строки локализованной ошибки).
Я попытался использовать XmlReader.Read и подсчитать количество узлов Element и EndElement. Таким образом, я знаю, когда я закончил читать первое целое XML-сообщение.
Однако есть несколько проблем. Если буфер еще не содержит всего сообщения, как я могу отличить XmlException от фактически недействительного, не-правильно сформированного сообщения? Другими словами, если перед чтением первого корня EndElement возникает исключение, как я могу решить, следует ли прервать соединение с ошибкой или собрать больше байтов из потока TCP?
Если исключение не происходит, XmlReader располагается в начале корня EndElement. Отбрасывание XmlReader в IXmlLineInfo дает мне текущие LineNumber и LinePosition, однако прямо не получается получить положение байта, где действительно заканчивается EndElement. Для этого мне пришлось бы преобразовать массив байтов в строку (с кодировкой, указанную в объявлении XML), искать LineNumber, LinePosition и преобразовывать это обратно в смещение байта. Я пытаюсь сделать это с помощью StreamReader.ReadLine, но считыватель потока не дает открытого доступа к текущей позиции байта.
Все эти швы очень неэлегантные и ненадежные. Интересно, есть ли у вас идеи для лучшего решения. Спасибо.