通过远程登录发送数据,无需按回车键
我最近开始搞砸Java套接字和telnet...
我希望用户能够连接到服务器,只需键入一个字母并将其发送到服务器,而无需按Enter键即可发送。我确信服务器没有办法设置它,但也许telnet有一个参数或可以允许这样做的东西?
也许如果我让用户键入或在运行telnet之前,这将起作用吗?(我知道只有UNIX!stty cbreak
stty raw
如果我可以让telnet来做到这一点,那么它就省去了我为这个功能编写一个特殊的客户端......
我最近开始搞砸Java套接字和telnet...
我希望用户能够连接到服务器,只需键入一个字母并将其发送到服务器,而无需按Enter键即可发送。我确信服务器没有办法设置它,但也许telnet有一个参数或可以允许这样做的东西?
也许如果我让用户键入或在运行telnet之前,这将起作用吗?(我知道只有UNIX!stty cbreak
stty raw
如果我可以让telnet来做到这一点,那么它就省去了我为这个功能编写一个特殊的客户端......
实际上,服务器有一种方法可以请求此内容:它称为 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_LINEMODE
LM_MODE
0
WILL ECHO
客户端(如果它支持 telnet 协商)将使用类似或“引用”的序列进行回复,例如您可以检测并从输入流中筛选出来的序列。IAC blah blah
IAC SB ... IAC SE
您应该能够通过 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)0xff
U+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();