Отправка данных по телнету без нажатия кнопки ввода
Я недавно начал возиться с сокетами Java и telnet...
Я хочу, чтобы пользователь мог подключиться к серверу, просто введите письмо и отправьте его на сервер, не нажимая клавишу ВВОД, чтобы отправить его. Я уверен, что у сервера нет способа настроить это, но, возможно, у telnet есть параметр или что-то, что могло бы позволить это?
Может быть, если я заставил пользователя напечатать stty cbreak
или же stty raw
до запуска telnet это будет работать? (Только UNIX, я знаю!)
Если я могу заставить telnet сделать это, то это избавляет меня от необходимости писать специальный клиент только для этой функции...
4 ответа
Вы должны быть в состоянии сделать это с помощью согласования параметров Telnet. По умолчанию в протоколе используется полудуплексный режим, и как минимум для интерактивного сеанса сервер должен согласовать параметр подавления перехода и параметр эха.
Как минимум, вы могли бы просто выплюнуть ff fb 01
ff fb 03
(будет эхом, будет подавлять-вперед) в начале сеанса, а затем ответить на любой ff fd 01
(сделать эхо) с ff fb 01
(откликнется) и ответит на любой ff fd 03
(сделать подавление-вперед) с ff fb 03
(будет подавлять добро).
Изменить, чтобы добавить, что переговоры о линейном режиме, упомянутые Беном Джексоном, являются лучшим ответом. Подавление разрешения не будет достаточным для большинства клиентов, подключающихся через порты, отличные от 23.
Однако я думаю, что другая проблема, с которой вы сталкиваетесь, заключается в том, что Java отправляет символы Unicode. Например, когда вы говорите (char)0xff
Java предполагает, что вы имеете в виду символ UTF-16 U+00ff
который ÿ
, Вероятно, он отправляет его через сокет с использованием кодировки UTF-8, поэтому клиент telnet видит два байта: c3 bf
который он передает и отображает как ÿ
,
Что вы можете сделать, так это явно указать Java использовать кодировку ISO-8859-1. Например, вы могли делать что-то подобное раньше:
out = new PrintStream(connection.getOutputStream());
out.print((char)0xff); // sends 0xc3 0xbf
out.print((char)0xfb); // sends 0xc3 0xbb
out.print((char)0x01); // sends 0x01
out.flush();
Вместо этого вы можете использовать OutputStreamWriter, чтобы указать желаемую кодировку:
out = new OutputStreamWriter(connection.getOutputStream(), "ISO-8859-1");
out.write((char)0xff); // sends 0xff
out.write((char)0xfb); // sends 0xfb
out.write((char)0x01); // sends 0x01
out.flush();
На самом деле сервер может запросить это: он называется согласованием параметров telnet. типично telnet
по умолчанию будет настраивать локальный tty в режиме "raw", когда вы используете порт 23 и режим "cooked" (или "line") на других портах. Линейный режим - это когда у вас есть минималистичное локальное редактирование, и данные отправляются, когда вы нажимаете клавишу возврата.
После отключения линейного режима вы можете отдельно настроить такие вещи, как локальное эхо.
РЕДАКТИРОВАТЬ: Я думаю, что разумная последовательность будет:
255, 253, 34, /* IAC DO LINEMODE */
255, 250, 34, 1, 0, 255, 240 /* IAC SB LINEMODE MODE 0 IAC SE */
255, 251, 1 /* IAC WILL ECHO */
Это позволяет TELOPT_LINEMODE
(34), а затем устанавливает линейный режим LM_MODE
в 0
(что я считаю правильным способом сказать клиенту не делать никаких локальных изменений). Наконец то сказано WILL ECHO
указав сервер будет эхо (так что клиент не будет).
Клиент (если он поддерживает согласование telnet) ответит с помощью следующих последовательностей: IAC blah blah
или "цитируемые" последовательности, такие как IAC SB ... IAC SE
который вы можете обнаружить и отфильтровать из вашего входного потока.
Чтобы настроить telnet для отправки данных без нажатия клавиши ввода, вы должны отключить опцию режима линии. Это делается с помощью подкоманды mode telnet:
telnet> mode character
Это включает режим персонажа за раз.
Вы должны увидеть документацию (например, страницу руководства) для своего клиента telnet.
Например, мой (реализация telnet krb5-1.6 в Linux) имеет mode character
команда, которая отключает локальную строковую буферизацию и немедленно отправляет большинство символов.
РЕДАКТИРОВАТЬ:
Отключение редактирования локальной линии в некоторых других клиентах, таких как PuTTY, приводит к тому же результату. PuTTY также имеет raw
режим соединения, который может быть полезен.
Обратите внимание, что если вы не возражаете против реализации некоторых частей протокола TELNET на сервере, вы также можете удаленно отключить редактирование локальной линии (опция LINEMODE TELNET).
Если вас не интересует интерактивность, вы также можете использовать netcat:
echo -n X | nc host 7777
К сожалению, во многих системах (таких как моя) netcat использует линейный буферизованный ввод-вывод.
Я советую использовать netcat для этих целей. Он может вести себя как мессенджер, не нажимая Enter. В поисках учебника по Netcat возвращаются тонны видео.