Как правильно передавать строки XML между пользовательским TCP-клиентом / сервером? - PullRequest
1 голос
/ 13 сентября 2009

Я работаю над проектом клиент / сервер C ++, где строки XML передаются через соединение TCP / IP. Мой вопрос о том, как правильно указать, что вся строка была получена. Я думал о завершенных нулем строках или сначала отправлял длину строки XML, чтобы клиент / сервер мог определить, когда получена полная строка.

Клиент может отправлять команды GET / SET, а сервер может отвечать, а также отправлять непрерывный поток результатов. Например: клиент отправляет <GET ID="DATA1" />, а сервер отвечает <ID="DATA1" VAL="..." /> Или сервер может отправлять непрерывный поток:

<ID="DATA1" VAL="..." />
<ID="DATA2" VAL="..." />
<ID="DATA3" VAL="..." />
<ID="DATA4" VAL="..." />

В этом случае клиент может получить за одно чтение:

<ID="DATA1" VAL="..." /><ID="DATA2" VAL="..." />

Или, если было отправлено большое количество данных, для чтения всей строки может потребоваться несколько операций чтения.

Использование нулевого символа завершения кажется немного упрощенным (и ломается, если строка в юникоде?), И отправка значения длины также кажется неудобной:

20<ID="DATA1" VAL="1" /> или <length=20><ID="DATA1" VAL="1" />

Это должно быть решено для TX / RX файлов HTML, я просто не могу понять это.

Я использую MFC C ++ (устаревший код) для сервера и .Net C ++ / CLI или C # для клиента.

Любая помощь очень ценится!

Ответы [ 5 ]

5 голосов
/ 13 сентября 2009

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

<data id="DATA1" val="..." />

или

Затем вы можете использовать SAX парсер для потока, который выдаст вам события при разборе узлов и атрибутов.

Затем я бы реализовал два типа ваших команд:

// individual commands
<get id="data_1"/>

// multiple commands
<multi>
  <data id="DATA1"/>
  <data id="DATA2"/>
  ...
</multi>
1 голос
/ 14 сентября 2009

Я вижу два варианта, которые имеют большой смысл, которые я использовал раньше:

1- Просто отправьте его и не прерывайте XML. Если XML верен, у него будет только один корневой узел. Вам не нужно прерывать его, поскольку клиент может анализировать его, пока не обнаружит, что у него есть полный XML-файл.

2 - использовать строки в стиле «Паскаль». Я нахожу это действительно легким, поскольку чтение может быть выполнено сразу, и это делает все остальные проблемы несуществующими. В основном, добавьте в ваш «строковый» документ целое число, равное количеству отправляемых байтов. Я делаю это особенно когда имеешь дело с TCP, так как я могу извлечь то, что я называю «пакетами» или группами полных данных, сразу.

0 голосов
/ 14 сентября 2009

Мне нравится идея простого разграничения CRLF, кажется, самая простая. По предоставленной ссылке будет ли это работать? (с CRLF == два байта 1013)

Отправить:

   <GET ID="DATA1" />CRLF

Ответ:

   <ID="DATA1" VAL="3" />CRLF
   <ID="DATA1" VAL="2" />CRLF
   <ID="DATA1" VAL="1" />CRLF
   ...

Как уже упоминалось в ответе 2, может возникнуть XML-ответ с несколькими строками. Может ли это вызвать проблемы с CRLF в каждой строке, а не в конце ответа? Разве CRLF не может естественным образом встречаться в многострочной XML-строке?

Ответ:

   <multi>CRLF
     <data id="DATA1"/>CRLF
     <data id="DATA2"/>CRLF
   </multi>CRLF
0 голосов
/ 14 сентября 2009

Я могу придумать три способа:

  • Опишите длину вне полосы: Это может быть немного похоже на HTTP header: CR уменьшает длину в ascii, тогда все последующие байты считаются в длина.
  • Ноль завершает строку. Нулевой символ уникален.
  • CR или LF завершают узел, и линейный протокол может читать XML.

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

0 голосов
/ 13 сентября 2009

Использование нулевого байта - правильный подход. он не должен (по крайней мере, afaik) ничего не нарушать в отношении юникода или другой кодировки и дает вам определенно большую гибкость, чем любая длина в байтах / длиннах.

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