如何让我的简单 Swing telnet 客户端正确显示字符?
我正在尝试在 Swing 中编写一个简单的 telnet 客户端(类似于 Putty)。我的基本功能正常工作,但我得到了有趣的转义字符,例如“Z [H [J””。我也没有像 putty 那样获得屏幕上的内容。
这是我的应用程序显示的内容:
FreeBSD/i386 (m-net.arbornet.org) (pts/15)
login:newuser 密码:
Z[H[J 欢迎来到 M-Net 美国第一个公共访问 UNIX 系统!
按任意键继续。
当我使用 putty 连接时,输入登录名和密码后,屏幕会清除 显示以下内容。关于如何实现同样的目标有什么想法吗?
FreeBSD/i386 (m-net.arbornet.org) (pts/6)
登录:newuser 密码: 欢迎来到 M-Net,美国第一个公共访问 UNIX 系统!
M-Net 是由 Arbornet, Inc.(一家 非营利性安娜堡公司。 M-Net 的使用完全免费——尽情享受! 如果您决定您足够喜欢 M-Net 并在以后成为支持者(M-Net 是 由用户贡献维持),登录后随时输入“支持” 到系统。感谢您致电 M-Net,欢迎您!
What's happening here
你好。我是新用户程序。我完全自动化了。我要教书 您对如何更有效地使用该系统有很少的了解。 然后我将继续问你几个问题。我给你一个 有机会纠正您的答案,然后我将为您创建一个帐户 (根据您的回答)。之后,我就完成了,我会让你继续 系统与您的新帐户。首先,请允许我告诉你更多一点 关于M-Net。
What is M-Net?
M-Net 首先是一个有趣的地方。我们希望您喜欢登录 M-Net——但 M-Net 也作为社区资源存在。 Arbornet, Inc.,
按任意键继续
下面是我的应用程序的完整可编译和可运行代码。运行后,单击“连接”(无需密码)即可查看我所描述的内容。这将打开一个到 arbornet.org(一个提供免费 shell 帐户的站点)的 telnet 连接,以 newuser 身份登录,无需密码。
package ui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.text.BadLocationException;
import org.apache.commons.net.telnet.TelnetClient;
public class SwingTelnetClient extends JFrame {
private static final long serialVersionUID = 1L;
JLabel lblServer = new JLabel();
JLabel lblUserId = new JLabel();
JLabel lblPassword = new JLabel();
JButton btnConnect = new JButton();
JButton btnDisconnect = new JButton();
JTextField txtServer = new JTextField();
JTextField txtUserId = new JTextField();
JPasswordField txtPassword = new JPasswordField();
JLabel lblCommand = new JLabel();
JTextArea txtConsole = new JTextArea();
JTextField txtCommand = new JTextField();
JScrollPane scrollPane = new JScrollPane();
PrintStream consolePrintStream = null;
MyTelnetClient client;
public SwingTelnetClient() {
setTitle("Simple Telnet Client");
JPanel panel = createMainPanel();
addListeners();
this.setPreferredSize(new Dimension(800, 400));
this.getContentPane().add(panel);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(createTopPanel(), BorderLayout.NORTH);
txtConsole.setColumns(50);
txtConsole.setSize(300, 300);
txtConsole.setBackground(Color.black);
txtConsole.setForeground(Color.green);
txtConsole.setFont(new Font("Terminal", 0, 16));
txtConsole.setFocusable(false);
scrollPane.getViewport().add(txtConsole);
panel.add(scrollPane, BorderLayout.CENTER);
panel.add(createBottomPanel(), BorderLayout.SOUTH);
return panel;
}
private void addListeners() {
btnConnect.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
client = new MyTelnetClient(txtServer.getText());
consolePrintStream = new PrintStream(new FilteredStream(client.getOut()));
System.setErr(consolePrintStream);
System.setOut(consolePrintStream);
client.connect(txtUserId.getText(), txtPassword.getText());
txtCommand.requestFocus();
}
});
btnDisconnect.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
client.disconnect();
txtConsole.setText("Disconnected");
txtUserId.requestFocus();
}
});
txtPassword.addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
btnConnect.doClick();
}
}
public void keyPressed(KeyEvent e) {
}
});
txtCommand.addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
String command = txtCommand.getText().trim();
if (command.equals("exit")) {
client.disconnect();
txtConsole.setText("Disconnected");
txtUserId.requestFocus();
} else if (command.equals("clear")) {
txtConsole.setText("");
} else {
client.sendCommand(command);
}
txtCommand.setText("");
}
}
public void keyPressed(KeyEvent e) {
}
});
txtServer.addFocusListener(new SelectAllFocusListener(txtServer));
txtUserId.addFocusListener(new SelectAllFocusListener(txtUserId));
txtPassword.addFocusListener(new SelectAllFocusListener(txtPassword));
}
private JPanel createTopPanel() {
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.RIGHT, 5, 5));
panel.setPreferredSize(new Dimension(300, 70));
lblServer.setText("Server");
lblUserId.setText("User Id");
lblPassword.setText("Password");
txtServer.setText("arbornet.org");
txtUserId.setText("newuser");
txtPassword.setText("");
btnConnect.setText("Connect");
btnConnect.setSize(30, 25);
btnDisconnect.setText("Disconnect");
btnDisconnect.setSize(30, 25);
txtServer.setColumns(20);
txtUserId.setColumns(15);
txtPassword.setColumns(15);
panel.add(lblServer);
panel.add(txtServer);
panel.add(lblUserId);
panel.add(txtUserId);
panel.add(lblPassword);
panel.add(txtPassword);
panel.add(btnConnect);
panel.add(btnDisconnect);
return panel;
}
private JPanel createBottomPanel() {
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.RIGHT, 5, 5));
lblCommand.setText("Execute Command");
txtCommand.setColumns(50);
panel.add(lblCommand);
panel.add(txtCommand);
return panel;
}
public static void main(String[] args) {
SwingTelnetClient main = new SwingTelnetClient();
main.pack();
main.show();
}
private void scrollToBottom() {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
int endPosition = txtConsole.getDocument().getLength();
Rectangle bottom = txtConsole.modelToView(endPosition);
txtConsole.scrollRectToVisible(bottom);
} catch (BadLocationException e) {
System.err.println("Could not scroll to " + e);
}
}
});
}
class SelectAllFocusListener implements FocusListener {
JTextField textField;
public SelectAllFocusListener(JTextField textField) {
this.textField = textField;
}
public void focusLost(FocusEvent e) {
}
public void focusGained(FocusEvent e) {
textField.selectAll();
}
}
class FilteredStream extends FilterOutputStream {
public FilteredStream(OutputStream aStream) {
super(aStream);
}
public void write(byte b[]) throws IOException {
String aString = new String(b);
txtConsole.append(aString);
}
public void write(byte b[], int off, int len) throws IOException {
String aString = new String(b, off, len);
txtConsole.append(aString);
scrollToBottom();
}
}
class MyTelnetClient {
private static final String ENCODING = "ISO-8859-1";
private TelnetClient telnet = new TelnetClient();
private InputStream in;
private PrintStream out;
private String prompt = "$";
ReaderThread readerThread;
public MyTelnetClient(String server) {
try {
// Connect to the specified server
telnet.connect(server, 23);
in = telnet.getInputStream();
out = new PrintStream(telnet.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
public void connect(String user, String password) {
try {
readUntil("login:");
write(user);
readUntil("Password:");
write(password);
startReading();
} catch (Exception e) {
e.printStackTrace();
}
}
public String readUntilPrompt() {
return readUntil(prompt + " ");
}
public void startReading() {
readerThread = new ReaderThread("reader", in);
readerThread.start();
}
public String readUntil(String pattern) {
try {
char lastChar = pattern.charAt(pattern.length() - 1);
StringBuffer sb = new StringBuffer();
char ch = (char) in.read();
while (true) {
System.out.print(ch);
sb.append(ch);
if (ch == lastChar) {
if (sb.toString().endsWith(pattern)) {
return sb.toString();
}
}
ch = (char) in.read();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void disconnect() {
try {
telnet.disconnect();
} catch (Exception e) {
}
}
public String sendCommand(String command) {
try {
write(command);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void write(String value) {
try {
out.println(value);
out.flush();
System.out.println(value);
} catch (Exception e) {
e.printStackTrace();
}
}
public InputStream getIn() {
return in;
}
public PrintStream getOut() {
return out;
}
class ReaderThread extends Thread {
InputStream is;
boolean keepRunning = true;
public ReaderThread(String str, InputStream is) {
super(str);
this.is = is;
}
public void run() {
while (true) {
try {
char ch = (char) in.read();
System.out.print(ch);
} catch (IOException e) {
// Swallow intentionally. Don't want stacktrace to
// appear in console.
}
}
}
}
}
}
I'm trying to write a simple telnet client in Swing (similar to Putty). I have the base functionality working, but I'm getting funny escape characters, like "Z [H [J". I'm also not getting a screen worth of contents like putty does.
This is what my application displays:
FreeBSD/i386 (m-net.arbornet.org) (pts/15)
login:newuser
Password:
Z[H[J Welcome to M-Net America's First Public-Access UNIX System!
Press any key to Continue.
When I connect using putty, after entering my login and password, the screen clears
the following displays. Any thoughts on how I can achieve the same?
FreeBSD/i386 (m-net.arbornet.org) (pts/6)
login: newuser
Password:
Welcome to M-Net, America's First Public-Acess UNIX System!
M-Net is a free-access community service provided by Arbornet, Inc., a
non-profit Ann Arbor corporation. Use of M-Net is absolutely free--enjoy!
If you decide you like M-Net enough to be a supporter later on (M-Net is
sustained by user contributions), type "support" any time after you log in
to the system. Thank you for calling M-Net, and welcome!
What's happening here
Hi. I'm the newuser program. I'm completely automated. I'm going to teach
you a very small amount about how to use this system more effectively.
Then I'm going to move on and ask you a few questions. I'll give you a
chance to correct your answers, and then I will create an account for you
(based on your answers). After that, I'm done, and I'll let you on the
system with your new account. First, allow me to tell you a little more
about M-Net.
What is M-Net?
M-Net is, first and foremost, a fun place. We hope you enjoy logging into
M-Net--but M-Net also exists as a community resource. Arbornet, Inc., the
Press any key to Continue
Below is the entire compilable and runnable code for my application. After running, click "Connect" (with no password) to see what I've described. This will open a telnet connection to arbornet.org (a site that provides free shell accounts) as logs in as newuser with no password.
package ui;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.text.BadLocationException;
import org.apache.commons.net.telnet.TelnetClient;
public class SwingTelnetClient extends JFrame {
private static final long serialVersionUID = 1L;
JLabel lblServer = new JLabel();
JLabel lblUserId = new JLabel();
JLabel lblPassword = new JLabel();
JButton btnConnect = new JButton();
JButton btnDisconnect = new JButton();
JTextField txtServer = new JTextField();
JTextField txtUserId = new JTextField();
JPasswordField txtPassword = new JPasswordField();
JLabel lblCommand = new JLabel();
JTextArea txtConsole = new JTextArea();
JTextField txtCommand = new JTextField();
JScrollPane scrollPane = new JScrollPane();
PrintStream consolePrintStream = null;
MyTelnetClient client;
public SwingTelnetClient() {
setTitle("Simple Telnet Client");
JPanel panel = createMainPanel();
addListeners();
this.setPreferredSize(new Dimension(800, 400));
this.getContentPane().add(panel);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(createTopPanel(), BorderLayout.NORTH);
txtConsole.setColumns(50);
txtConsole.setSize(300, 300);
txtConsole.setBackground(Color.black);
txtConsole.setForeground(Color.green);
txtConsole.setFont(new Font("Terminal", 0, 16));
txtConsole.setFocusable(false);
scrollPane.getViewport().add(txtConsole);
panel.add(scrollPane, BorderLayout.CENTER);
panel.add(createBottomPanel(), BorderLayout.SOUTH);
return panel;
}
private void addListeners() {
btnConnect.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
client = new MyTelnetClient(txtServer.getText());
consolePrintStream = new PrintStream(new FilteredStream(client.getOut()));
System.setErr(consolePrintStream);
System.setOut(consolePrintStream);
client.connect(txtUserId.getText(), txtPassword.getText());
txtCommand.requestFocus();
}
});
btnDisconnect.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
client.disconnect();
txtConsole.setText("Disconnected");
txtUserId.requestFocus();
}
});
txtPassword.addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
btnConnect.doClick();
}
}
public void keyPressed(KeyEvent e) {
}
});
txtCommand.addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ENTER) {
String command = txtCommand.getText().trim();
if (command.equals("exit")) {
client.disconnect();
txtConsole.setText("Disconnected");
txtUserId.requestFocus();
} else if (command.equals("clear")) {
txtConsole.setText("");
} else {
client.sendCommand(command);
}
txtCommand.setText("");
}
}
public void keyPressed(KeyEvent e) {
}
});
txtServer.addFocusListener(new SelectAllFocusListener(txtServer));
txtUserId.addFocusListener(new SelectAllFocusListener(txtUserId));
txtPassword.addFocusListener(new SelectAllFocusListener(txtPassword));
}
private JPanel createTopPanel() {
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.RIGHT, 5, 5));
panel.setPreferredSize(new Dimension(300, 70));
lblServer.setText("Server");
lblUserId.setText("User Id");
lblPassword.setText("Password");
txtServer.setText("arbornet.org");
txtUserId.setText("newuser");
txtPassword.setText("");
btnConnect.setText("Connect");
btnConnect.setSize(30, 25);
btnDisconnect.setText("Disconnect");
btnDisconnect.setSize(30, 25);
txtServer.setColumns(20);
txtUserId.setColumns(15);
txtPassword.setColumns(15);
panel.add(lblServer);
panel.add(txtServer);
panel.add(lblUserId);
panel.add(txtUserId);
panel.add(lblPassword);
panel.add(txtPassword);
panel.add(btnConnect);
panel.add(btnDisconnect);
return panel;
}
private JPanel createBottomPanel() {
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout(FlowLayout.RIGHT, 5, 5));
lblCommand.setText("Execute Command");
txtCommand.setColumns(50);
panel.add(lblCommand);
panel.add(txtCommand);
return panel;
}
public static void main(String[] args) {
SwingTelnetClient main = new SwingTelnetClient();
main.pack();
main.show();
}
private void scrollToBottom() {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
int endPosition = txtConsole.getDocument().getLength();
Rectangle bottom = txtConsole.modelToView(endPosition);
txtConsole.scrollRectToVisible(bottom);
} catch (BadLocationException e) {
System.err.println("Could not scroll to " + e);
}
}
});
}
class SelectAllFocusListener implements FocusListener {
JTextField textField;
public SelectAllFocusListener(JTextField textField) {
this.textField = textField;
}
public void focusLost(FocusEvent e) {
}
public void focusGained(FocusEvent e) {
textField.selectAll();
}
}
class FilteredStream extends FilterOutputStream {
public FilteredStream(OutputStream aStream) {
super(aStream);
}
public void write(byte b[]) throws IOException {
String aString = new String(b);
txtConsole.append(aString);
}
public void write(byte b[], int off, int len) throws IOException {
String aString = new String(b, off, len);
txtConsole.append(aString);
scrollToBottom();
}
}
class MyTelnetClient {
private static final String ENCODING = "ISO-8859-1";
private TelnetClient telnet = new TelnetClient();
private InputStream in;
private PrintStream out;
private String prompt = "$";
ReaderThread readerThread;
public MyTelnetClient(String server) {
try {
// Connect to the specified server
telnet.connect(server, 23);
in = telnet.getInputStream();
out = new PrintStream(telnet.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
public void connect(String user, String password) {
try {
readUntil("login:");
write(user);
readUntil("Password:");
write(password);
startReading();
} catch (Exception e) {
e.printStackTrace();
}
}
public String readUntilPrompt() {
return readUntil(prompt + " ");
}
public void startReading() {
readerThread = new ReaderThread("reader", in);
readerThread.start();
}
public String readUntil(String pattern) {
try {
char lastChar = pattern.charAt(pattern.length() - 1);
StringBuffer sb = new StringBuffer();
char ch = (char) in.read();
while (true) {
System.out.print(ch);
sb.append(ch);
if (ch == lastChar) {
if (sb.toString().endsWith(pattern)) {
return sb.toString();
}
}
ch = (char) in.read();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void disconnect() {
try {
telnet.disconnect();
} catch (Exception e) {
}
}
public String sendCommand(String command) {
try {
write(command);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void write(String value) {
try {
out.println(value);
out.flush();
System.out.println(value);
} catch (Exception e) {
e.printStackTrace();
}
}
public InputStream getIn() {
return in;
}
public PrintStream getOut() {
return out;
}
class ReaderThread extends Thread {
InputStream is;
boolean keepRunning = true;
public ReaderThread(String str, InputStream is) {
super(str);
this.is = is;
}
public void run() {
while (true) {
try {
char ch = (char) in.read();
System.out.print(ch);
} catch (IOException e) {
// Swallow intentionally. Don't want stacktrace to
// appear in console.
}
}
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要解析服务器发送给您的转义代码。这可能有点繁琐,因为您必须将其作为 telnet 解析之上的单独解析层(它检测并处理 IAC 序列等)来执行此操作,并且没有什么可以阻止服务器一次向您发送一个字节的数据。
You'll need to parse the escape codes the server is sending you. This can be a little fiddly, because you'll have to do this as a separate parsing layer over the top of your telnet parsing (which detects and handles the
IAC
sequences and such), and there's nothing stopping the server sending you data one byte at a time.