我最近开始搞乱Java套接字和telnet ......
我希望用户能够连接到服务器,只需键入一个字母并将其发送到服务器,而无需按Enter键发送它。我确定服务器没有办法设置它,但也许telnet有一个参数或者什么可以允许这个?
也许如果我让用户在运行telnet之前键入stty cbreak
或stty raw
,这可行吗? (仅限UNIX,我知道!)
如果我可以通过telnet来执行此操作,那么我只需要为此功能编写一个特殊客户端就可以了...
答案 0 :(得分:8)
实际上 是服务器请求的一种方式:它叫做telnet option negotiation。通常telnet
将默认在“原始”模式下配置本地tty,当您在其他端口上使用端口23和“cooked”(或“line”)模式时。行模式是您进行简约本地编辑的地方,当您点击返回时会发送数据。
禁用linemode后,您可以单独配置本地回声等内容。
编辑:我认为合理的顺序是: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),然后将linemode LM_MODE
设置为0
(我认为这是告诉客户端不要进行任何本地编辑的正确方法)。最后它说WILL ECHO
表示服务器将回显(因此客户端不会)。
客户端(如果它支持telnet协商)将回复IAC blah blah
或“引用”序列之类的序列,例如IAC SB ... IAC SE
,您可以检测并过滤掉输入流。
答案 1 :(得分:3)
您应该可以通过telnet选项协商来执行此操作。 协议默认为半双工模式,至少对于交互式会话,服务器应协商suppress go ahead option和echo option。
至少你可以在会话开始时吐出ff fb 01
ff fb 03
(会回应,会抑制 - 先行),然后回复任何{{1使用ff fd 01
(将回显)(回声)并使用ff fb 01
回复任何ff fd 03
(执行抑制前进)(将禁止前进)。德尔>
编辑添加Ben Jackson提到的线路模式协商是一个更好的答案。对于大多数在23以外的端口上连接的客户端,抑制前进是不够的。
但是我认为你遇到的另一个问题是Java正在发送Unicode字符。例如,当您说ff fb 03
时,Java假定您指的是(char)0xff
的UTF-16字符U+00ff
。它可能使用UTF-8编码通过套接字发送它,因此telnet客户端看到两个字节:ÿ
它传递并显示为c3 bf
。
您可以做的是明确告诉Java使用ISO-8859-1编码。例如,您之前可能已经做过类似的事情:
ÿ
相反,您可以使用OutputStreamWriter指定所需的编码:
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();
答案 2 :(得分:2)
您需要查看telnet客户端的文档(例如手册页)。
例如我的(Linux上的krb5-1.6 telnet实现)有一个mode character
命令,可以关闭本地线路缓冲并立即发送大多数字符。
编辑:
禁用某些其他客户端(例如PuTTY)中的本地行编辑具有相同的结果。 PuTTY还具有可能有用的raw
连接模式。
请注意,如果您不介意在服务器上实现TELNET协议的某些部分,您还可以远程禁用本地线路编辑(LINEMODE TELNET选项)。
如果您不关心交互性,您也可以使用netcat:
echo -n X | nc host 7777
不幸的是,在许多系统(例如我的)上,netcat使用行缓冲I / O.
答案 3 :(得分:1)
我的建议是将netcat用于此目的。它可以像即时通讯一样,无需按Enter键。搜索netcat教程会返回大量视频。
答案 4 :(得分:0)
要将telnet配置为不按Enter即可发送数据,应禁用线路模式选项。这是通过模式telnet子命令完成的:
telnet> mode character
这将在时间模式下启用字符。