通过telnet发送数据而无需按Enter键

我最近开始搞乱Java套接字和telnet ……

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

也许如果我让用户在运行telnet之前键入stty cbreakstty raw ,这可行吗? (仅限UNIX,我知道!)

如果我可以通过telnet来执行此操作,那么我将不得不为此function编写一个特殊的客户端…

您应该可以通过telnet选项协商来执行此操作。 协议默认为半双工模式,并且至少对于交互式会话,服务器应协商suppress going ahead选项和echo选项 。

在最小的时候你可以在会话开始时吐出ff fb 01 ff fb 03 (会回显,会抑制 – 反超),然后用ff fb 01回复任何ff fd 01 (做回声)(将回声)并用ff fb 03回复任何ff fd 03 (做抑制前进)(将禁止前进)。

编辑添加Ben Jackson提到的线路模式协商是一个更好的答案。 对于大多数连接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选项协商 。 通常,当您在其他端口上使用端口23和“cooked”(或“line”)模式时, telnet将默认以“原始”模式配置本地tty。 行模式是您进行简约本地编辑的地方,当您点击返回时会发送数据。

禁用linemode后,您可以单独配置本地echo等内容。

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

 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_MODE0 (我认为这是告诉客户端不做任何本地编辑的正确方法)。 最后它说WILL ECHO表示服务器将回显(因此客户端不会)。

客户端(如果它支持telnet协商)将回复IAC blah blah或“引用”序列之类的序列,如IAC SB ... IAC SE ,您可以检测并过滤输入流。

您需要查看telnet客户端的文档(例如手册页)。

例如,我的(Linux上的krb5-1.6 telnet实现)有一个mode character命令,它关闭本地线路缓冲并立即发送大多数字符。

编辑:

禁用某些其他客户端(例如PuTTY)中的本地行编辑具有相同的结果。 PuTTY还具有可能有用的raw连接模式。

请注意,如果您不介意在服务器上实现TELNET协议的某些部分,您还可以远程禁用本地线路编辑(LINEMODE TELNET选项)。

如果你不关心交互性,你也可以使用netcat:

 echo -n X | nc host 7777 

不幸的是,在许多系统(例如我的)上,netcat使用线路缓冲的I / O.

我建议使用netcat用于此目的。 它可以像即时信使一样,无需按Enter键。 搜索netcat教程会返回大量video。