Как узнать, что пакет данных полностью получен в telnet?

Я пишу игрушечный клиент MUD, который использует сокет TCP/IP для подключения к телнет сервер.

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

Теперь проблема возникает, когда ответ длинный и получен в 2 или более пакетах TCP/IP, и поэтому регулярные выражения не будут совпадать, когда я запускаю их в ответах, так как они еще не завершены (первая или вторая часть не будут совпадать по отдельности ).

Итак, вопрос в том, как я узнаю, что сервер отправил пакет данных, прежде чем запускать на них мои регулярные выражения.


person Farzad Bekran    schedule 30.03.2015    source источник


Ответы (3)


Короткий ответ: нет

TCP/IP — это последовательный протокол, в котором нет понятия пакетов.

Если ваш протокол прикладного уровня использует пакеты (большинство из них), у вас есть два варианта:

  • использовать транспортный уровень, изначально поддерживающий пакеты (UDP, SCTP,...)

  • добавить информацию о пакетировании в поток данных

Самый простой способ добавить информацию о пакетировании — добавить символы-разделители (обычно \n); очевидно, вы не можете использовать разделитель в полезной нагрузке, так как он уже зарезервирован для других целей.

Если вам нужно иметь возможность передавать любой символ в полезной нагрузке (поэтому вы не можете зарезервировать разделитель), используйте что-то вроде SLIP поверх TCP/IP

person umläute    schedule 30.03.2015
comment
Я знаю, что он не имеет понятия о пакетах. но мне нужно как-то определить, не поступают ли данные, пока я не отправлю следующую команду. иногда данные заканчиваются на '\n', а иногда на какой-то другой символ, поэтому сервер явно не заботится о разделителе. - person Farzad Bekran; 30.03.2015
comment
Теперь я так понимаю, что вы не писали сервер и не можете его изменить. В этом случае вам придется разбираться в каждом конкретном случае. - person gia; 30.03.2015
comment
да, так как лучше всего это сделать? так как сервер может быть другим в любом случае. я думал о том, чтобы подождать около 200 мс, прежде чем действовать с данными... - person Farzad Bekran; 30.03.2015

вы можете сохранить стек, добавить в него пакеты, продолжать тестирование, пока не получите полный ответ

Если MUD должен воспроизводиться (почти) исключительно клиентом (а не самим telnet), вы можете добавить разделители, снова иметь стек, но не тестируйте вслепую, тестируйте, когда вы получите разделитель.

Если есть команда, которую вы можете отправить, которая не влияет на игровой процесс, но имеет постоянный ответ от сервера (например, пинг), вы можете использовать ее как своего рода разделитель.

person gia    schedule 30.03.2015
comment
вопрос в том, что такое разделитель? и что значит играет (почти) исключительно клиент (не сам телнет)? - person Farzad Bekran; 30.03.2015
comment
разделитель - это то, что вы хотите, прямо сейчас я разделяю свои предложения запятыми, а мои слова - любыми не буквами, вам просто нужно найти или определить разделитель, который последовательно отделяет ваши сообщения друг от друга. Если игрок будет подключаться через сам телнет, а не через ваш клиент, и, например, ваш разделитель %%%, он увидит эти %%%, и вы можете этого не захотеть. - person gia; 30.03.2015
comment
здесь небольшое недоразумение: серверная часть не находится под моим контролем, я просто пишу общий клиент грязи. поэтому я не могу заставить сервер добавлять разделители в конец данных. - person Farzad Bekran; 30.03.2015
comment
используйте первый абзац моего ответа, затем смешайте его со вторым, когда это возможно. Сохраняйте стек, и всякий раз, когда вы чувствуете, что строка завершена, обрабатывайте ее (например, вы обнаружили полное командное слово или прошло 30 секунд, а пакетов больше нет › В этом случае я бы вышел из системы). Если определенные команды разделены, воспользуйтесь преимуществом в этих случаях. - person gia; 30.03.2015
comment
это в значительной степени то, о чем я думал, но проблема в том, что это создает ненужную задержку между получением данных и их отображением пользователю. - person Farzad Bekran; 30.03.2015
comment
Если вы знаете игру наизусть, вы можете знать, в каком состоянии игры вы находитесь, то вы можете предсказать характер ответа по первым полученным байтам, может быть, даже по вашей собственной команде :) Это немного хардкорное решение хотя. - person gia; 30.03.2015
comment
затем подождите x раз, играйте с числами, пока не будете довольны, имейте случаи сбоя, когда вы получаете пакеты, которых не ожидали - person gia; 30.03.2015

Возможно, вы слишком много думаете об этом. Почти все муты ограничивают строки LF, то есть \n (некоторые чудаковатые серверы будут использовать CRLF, \r\n или даже \n\r). Так что буферизируйте ввод и сканируйте разделитель \n. Когда вы найдете его, переместите строку из входного буфера, а затем запустите свои регулярные выражения.

Особым случаем является команда telnet IAC GA, которую некоторые муты используют для обозначения подсказок. Прочтите Telnet RFC для получения более подробной информации, https://tools.ietf.org/html/rfc854. и проведите небольшое исследование по проблемам, связанным с грязью, например, http://cryosphere.net/mud-protocol. HTML .

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

person georgek    schedule 30.03.2015
comment
проблема с этим решением будет заключаться в том, что каждая строка заканчивается переводом строки, например, вы отправляете «карту» и получаете карту вашего окружения в формате ASCII. И я видел подсказки, которые просто заканчиваются на «›» и ничего более. - person Farzad Bekran; 30.03.2015
comment
Неструктурированные данные (например, «карта», команда «помощь») — это проблема для грязей в целом, и вы не сможете решить ее на том уровне, о котором спрашиваете, если только у вас нет контроля над сервером и клиент. Подсказки, оканчивающиеся на «›», могут иметь после себя LF или IAC GA. Вы сканируете IAC, не так ли? - person georgek; 31.03.2015
comment
Я сканирую РХХ, к сожалению, грязь играет по своим правилам. Я использую земляного волка в качестве образца грязи прямо сейчас, и он заканчивает подсказку знаком «›» и ничего больше. Я могу изменить формат подсказки с помощью некоторых команд в грязи, но, как правило, для универсального клиента грязи не рекомендуется полагаться на предопределенный формат. и хорошо зарекомендовавшие себя клиенты, которые я использую, без проблем обнаруживают любые подсказки. - person Farzad Bekran; 31.03.2015