通过远程登录发送数据,无需按回车键

2022-09-03 06:55:00

我最近开始搞砸Java套接字和telnet...

我希望用户能够连接到服务器,只需键入一个字母并将其发送到服务器,而无需按Enter键即可发送。我确信服务器没有办法设置它,但也许telnet有一个参数或可以允许这样做的东西?

也许如果我让用户键入或在运行telnet之前,这将起作用吗?(我知道只有UNIX!stty cbreakstty raw

如果我可以让telnet来做到这一点,那么它就省去了我为这个功能编写一个特殊的客户端......


答案 1

实际上服务器有一种方法可以请求此内容:它称为 telnet 选项协商。通常,当您在其他端口上使用端口 23 和“熟”(或“线路”)模式时,将默认配置为“原始”模式下的本地 tty。行模式是进行极简的本地编辑,并在您点击返回时发送数据。telnet

禁用行模式后,您可以单独配置本地回显等内容。

编辑:我认为一个合理的顺序是:

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 */

启用(34),然后将行模式设置为(我认为这是告诉客户端不要进行任何本地编辑的正确方法)。最后,它说指示服务器将回显(因此客户端不会)。TELOPT_LINEMODELM_MODE0WILL ECHO

客户端(如果它支持 telnet 协商)将使用类似或“引用”的序列进行回复,例如您可以检测并从输入流中筛选出来的序列。IAC blah blahIAC SB ... IAC SE


答案 2

您应该能够通过 telnet 选项协商来执行此操作。该协议默认为半双工模式,对于交互式会话,服务器至少应协商抑制继续选项echo 选项

在最低限度上,您可以在会话开始时吐出ff fb 01 ff fb 03(将回声,将抑制继续),然后用ff fb 01(将回显)回复任何ff fd 01(做回声),并使用ff ffb 03回复任何ff fd 03(执行抑制-继续)。

编辑以补充本·杰克逊提到的线模式协商是一个更好的答案。对于在 23 以外的端口上连接的大多数客户端来说,抑制批准是不够的。

但是,我认为您遇到的另一个问题是Java正在发送Unicode字符。例如,当您说时,Java 假设您指的是 UTF-16 字符,即 。它可能使用 UTF-8 编码通过套接字发送它,因此 telnet 客户端会看到两个字节:它传递并显示为 。(char)0xffU+00ffÿ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();

推荐