1 概述
数据流图
Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式。它为用户提供了在本地计算机上完成远程主机工作的能力。远程登录是指用户使用Telnet命令,使自己的计算机暂时成为远程主机的一个仿真终端的过程。仿真终端等效于一个非智能的机器,它只负责把用户输入的每个字符传递给主机,再将主机输出的每个信息回显在屏幕上。
2 技术实现
采用Java语言,其中使用Apache Commons Net,TelnetClient是commons-net-3.6.jar(根据自己情况下载)下的一个类,用于实现telnet连接。所需的jar包下载地址:http://commons.apache.org/proper/commons-net/
使用java连接telnet进行操作的注意
- 1.telnet有VT100、 VT52、 VT220 、VTNT、 ANSI等协议。Demo中使用VT100。
- 2.vt100控制码(ansi控制码)过滤的问题,可以过滤,也可以在服务设置不要。不过滤都是一些乱码。是以\033[***一个字母结尾的格式。
- 3.中文乱码的问题。new String(old.getBytes(“ISO8859-1”),“GBK”)。
- 4.如何判断读取到最后了。一demo中使用readUntil(),二有使用线程。
- 5.选择telnet的java包问题,包有很多,比如appache(commons-net-3.6.jar), ganymed(ganymed-ssh2-build210.jar),javaexpect(smart-0.1-SNAPSHOT-jar-with-dependencies.jar)。Demo中使用Apache。
- 6.Write要flush()才发送。
Demo实现流程图
3 技术总结
TelnetClient实际是通过socket实现的。
通过InputStream读取服务器返回的数据,自己根据数据判断什么时候可以命令。
通过OutputStream向服务器发送命令,由于每次写完命令后,需要写入一个换行符,所以使用printStream会省事点(println方法写入命令后自动加入换行符)。
在不清楚命令返回结果时,可以使用windows telnet连接到设备,输入命令,观察结果,程序根据结果去修改就ok。
TelnetClient实际上是模仿一个Telnet客户端,命令输入和获取和客户端输入命令返回结果是一样的。
源码实现
package com.internet;
/**
* .Description:TODO
* .@Author:
* .@Date: 2020/1/9 17:11
*/
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.SocketException;
import org.apache.commons.net.telnet.TelnetClient;
/**
*
* 使用java连接telnet进行操作的注意
1.telnet有VT100 VT52 VT220 VTNT ANSI等协议。
我用vt100。
2.vt100控制码(ansi控制码)过滤的问题,可以过滤,也可以在服务设置不要。
不过滤都是一些乱码。是以\033[***一个字母结尾的格式。
3.中文乱码的问题。
new String(old.getBytes("ISO8859-1"),"GBK")。
4.如何判断读取到最后了。
一有readUntil(),二有使用线程。
5.选择telnet的java包问题,包有很多,比如appache(commons-net-3.1.jar), ganymed(ganymed-ssh2-build210.jar),javaexpect(smart-0.1-SNAPSHOT-jar-with-dependencies.jar)
我使用appache。javaexpect有带的vt100控制码过滤,我没有仔细研究。
6.write要flush()才发送。
*
*
* telnet操作类。使用appache的net.Telnet包,对vt100控制代码(即ansi控制码)进行简单过滤。
*
* @author chruan
* @version 1.0
*/
public class Telnet {
Object lock = new Object();
TelnetClient telnet = null;
String hostname;
int hostport = 23;
String user;
String password;
private InputStream in;
private PrintStream out;
private static final String ORIG_CODEC = "ISO8859-1";
private static final String TRANSLATE_CODEC = "GBK";
public Telnet(String hostname, int hostport, String user, String password) throws SocketException, IOException {
super();
this.hostname = hostname;
this.hostport = hostport;
this.user = user;
this.password = password;
// VT100 VT52 VT220 VTNT ANSI
telnet = new TelnetClient("VT100");
telnet.connect(hostname, hostport);
in = telnet.getInputStream();
out = new PrintStream(telnet.getOutputStream());
readUntil("Username:");
write(user);
write("\n");
readUntil("Password:");
write(password);
write("\n");
}
public void readToEnd() {
ReadThread readThread = new ReadThread();
readThread.start();
try {
readThread.join();
} catch (Exception e) {
}
readThread = null;
}
public void readUntil(String str) {
char last = str.charAt(str.length() - 1);
String[] ss;
try {
StringBuffer sb = new StringBuffer();
char c;
int code = -1;
boolean ansiControl = false;
boolean start = true;
while ((code = (in.read())) != -1) {
c = (char) code;
//vt100控制码都是以\033开头的。
if (c == '\033') {
ansiControl = true;
int code2 = in.read();
char cc = (char) code2;
if (cc == '[' || cc == '(') {
}
}
if (!ansiControl) {
if (c == '\r') {
//这里是命令行中的每一句反馈
String olds = new String(sb.toString().getBytes(
ORIG_CODEC), TRANSLATE_CODEC);
System.out.println(olds);
if (sb.lastIndexOf(str) != -1) {
break;
}
sb.delete(0, sb.length());
} else if (c == '\n'){
} else{
sb.append(c);
}
if (sb.lastIndexOf(str) != -1) {
break;
}
}
if (ansiControl) {
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
|| c == '"') {
ansiControl = false;
}
}
}
System.out.println(new String(sb.toString().getBytes(ORIG_CODEC), TRANSLATE_CODEC));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 读取分析结果
*
* @param pattern
* @return
*/
public String read(String pattern) {
try {
char lastChar = pattern.charAt(pattern.length() - 1);
StringBuffer sb = new StringBuffer();
char ch = (char) in.read();
while (true) {
sb.append(ch);
if (ch == lastChar) {
if (sb.toString().endsWith(pattern)) {
return sb.toString().substring(sb.toString().indexOf("D"),sb.toString().length());
}
}
ch = (char) in.read();
//System.out.print(ch);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void write(String s) {
try {
out.write(s.getBytes());
out.flush();
//System.out.println(s);
} catch (Exception e) {
}
}
/**
* 完成之后必须关闭
*/
public void close() {
if (out != null) {
out.close();
}
if (in != null) {
try {
in.close();
} catch (IOException e1) {
}
}
if (telnet != null) {
try {
telnet.disconnect();
} catch (IOException e) {
}
}
}
public void doJob() {
// restartTerminal();
counter();
}
private void counter() {
//演示在一台机器上远程登录另一台计算机
try {
//readUntil("Switch#");
write("Information");
write("\n");
write("show others");
write("\n");
System.out.println("**************");
String s = read("way");
System.out.println("s为:\n"+s);
System.out.println("**************");
//write("show state");
readToEnd();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
}
public static void main(String[] args) {
String hostname = "10.10.0.101";
int hostport = 23;
String user = "admin";
String password = "admin";
Telnet helper = null;
try {
helper = new Telnet(hostname, hostport, user, password);
helper.doJob();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (helper != null) {
helper.close();
}
}
}
/**
* 读取主线程,负责管理子线程。防止读取时不动了,这时就抛弃读取子线程
*
*/
class ReadThread extends Thread {
@Override
public void run() {
//只能一个读取
synchronized (lock) {
SubReadThread sub = new SubReadThread();
sub.start();
int last = sub.count;
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
if (last == sub.count) {
sub.stop();
break;
} else {
last = sub.count;
}
}
String s = sub.sb.toString();
try {
System.out.println(new String(s.getBytes(ORIG_CODEC),
TRANSLATE_CODEC));
} catch (UnsupportedEncodingException e) {
System.out.println(s);
}
sub = null;
}
System.out.println("===========ReadThread end=============");
}
}
/**
* 读取子线程,完成实际读取
*
*/
class SubReadThread extends Thread {
int count = 0;
StringBuffer sb = new StringBuffer();
public void read() {
try {
char c;
int code = -1;
boolean ansiControl = false;
boolean start = true;
while ((code = (in.read())) != -1) {
count++;
c = (char) code;
if (c == '\033') {
ansiControl = true;
int code2 = in.read();
char cc = (char) code2;
count++;
if (cc == '[' || cc == '(') {
}
}
if (!ansiControl) {
if (c == '\r') {
String olds = new String(sb.toString().getBytes(
ORIG_CODEC), TRANSLATE_CODEC);
System.out.println(olds);
sb.delete(0, sb.length());
} else if (c == '\n') {
;
}else {
sb.append(c);
}
}
if (ansiControl) {
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
|| c == '"') {
ansiControl = false;
}
}
}
} catch (Exception e) {
}
}
@Override
public void run() {
read();
}
}
}