//telnet 的命令格式:IAC+命令码+选项码
final byte IAC = (byte) 255;
//协商的命令码
final byte DONT = (byte) 254;
final byte DO = (byte) 253;
final byte WONT = (byte) 252;
final byte WILL = (byte) 251;
final byte SB = (byte) 250;
final byte SE = (byte) 240;
//协商的选项码
final char IS = '0';
final char SEND = '1';
final char INFO = '2';
final char VAR = '0';
final char VALUE = '1';
final char ESC = '2';
final char USERVAR = '3';
final int MAX = 1000000;
Socket s;
InputStream in ;
OutputStream out;
PrintStream ps;
DataInputStream conIn;
BufferedInputStream dataIn;
// String sysIn="open\r\n";
byte[] recvByte; //接收的字节数据
String recv; //转换后的字符
byte[] sendByte; //发送的字节数据
String send; //发送的源字符
int read; //接收的字节数据的个数
int write; //发送的字节数据个数
boolean hasData; //标志套接字中的输入流是否还有未读完的数据
String ip;
int port;
public Socket2Telnet(Socket s, String ip, int port) {
this.s = s;
this.ip = ip;
this.port = port;
}
//关闭socket连接
public void closeConnection(Socket s, InputStream in , OutputStream out) {
if (s.isConnected() && !s.isClosed()) {
try { in .close();
out.close();
s.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
//解析协商数据
public void Compile() {
//存在协商控制命令选项时需要解析并应答
write = 0;
for (int i = 0; i < read;) {
if (recvByte[i] == IAC) { //255
// System.out.println("get IAC!"+(int)(recvByte[0]& 0xff)+recvByte[0]);
sendByte[write] = recvByte[i];
if (recvByte[i + 2] == 1 || recvByte[i + 2] == 3) {
if (recvByte[i + 1] == DO) { //253
// System.out.println("get DO!"+(int)(recvByte[1]& 0xff));
sendByte[write + 1] = WILL;
sendByte[write + 2] = recvByte[i + 2];
write += 3;
i += 3;
} else if (recvByte[i + 1] == WILL) { //251
// System.out.println("get WILL !"+(int)(recvByte[1]& 0xff)+recvByte[1]);
sendByte[write + 1] = DO;
sendByte[write + 2] = recvByte[i + 2];
write += 3;
i += 3;
} else if (recvByte[i + 1] == WONT) { //252
// System.out.println("get WONT!"+(int)(recvByte[1]&0xff)+recvByte[1]);
sendByte[write + 1] = DONT;
sendByte[write + 2] = recvByte[i + 2];
write += 3;
i += 3;
} else if (recvByte[i + 1] == DONT) { //254
// System.out.println("get DONT! "+(int)(recvByte[1]&0xff)+recvByte[1]);
sendByte[write + 1] = WONT;
sendByte[write + 2] = recvByte[i + 2];
write += 3;
i += 3;
} else if (recvByte[i + 1] == SB) { //250
System.out.println("get SB ! " + (int)(recvByte[1] & 0xff) + recvByte[1]);
if (recvByte[i + 3] == SEND) {
System.out.println("get SEND!" + recvByte[3]);
sendByte[write + 1] = recvByte[i + 1];
sendByte[write + 2] = recvByte[i + 2];
sendByte[write + 3] = IS;
sendByte[write + 4] = IAC;
sendByte[write + 5] = SE;
System.out.println("YES, get a SD and SEND !");
write += 6;
i += 3;
}
}
// System.out.println(" and recvByte[2] "+(int)(recvByte[2]&0xff)+recvByte[2]+(char)(recvByte[2]&0xff));
// ps.write(sendByte,0,write);
// ps.flush();
} else {
if (recvByte[i + 1] == DONT || recvByte[i + 1] == DO) {
sendByte[write + 1] = WONT;
sendByte[write + 2] = recvByte[i + 2];
} else if (recvByte[i + 1] == WILL || recvByte[i + 1] == WONT) {
sendByte[write + 1] = DONT;
sendByte[write + 2] = recvByte[i + 2];
}
write += 3;
i += 3;
}
} else {
return;
}
}
}
//sokcet连接服务器,收发数据
public void run() {
try {
s.connect(new InetSocketAddress(ip, port));
System.out.println("socket Connect success!");
System.out.println("Server IP:" + s.getInetAddress() + ",port :" + s.getPort() + "\n");
//获取套接字的输入和输出流
in =s.getInputStream();
out = s.getOutputStream();
conIn = new DataInputStream(System. in );
dataIn = new BufferedInputStream( in );
ps = new PrintStream(out);
//初始化
recvByte = new byte[MAX];
sendByte = new byte[MAX];
recv = new String("");
send = new String("");
write = read = 0;
while (true) {
read = write = 0;
Thread.sleep(2000);
if ((read = in.read(recvByte)) > 0) {
hasData = true;
} else hasData = false;
// System.out.println("recv data "+read+" byte!");
// System.out.println("recv msg :"+new String(recvByte,"UTF-8"));
// for(int i=0;i<read;i++)
// System.out.print((char)(recvByte[i]&0xff));
// System.out.println("");
for (int i = 0; i < read; i++) System.out.print((int)(recvByte[i] & 0xff) + " ");
System.out.println("\n");
//协商的应答
if (read > 0) {
Compile();
if (write > 0) {
ps.write(sendByte, 0, write);
// ps.flush();
}
}
System.out.println("read = " + read + ",write = " + write);
Thread.sleep(3000);
//服务器没有响应时,等待用户输入命令;
//服务器返回输入命令时,告知用户命令,并读取用户输入并发送给服务器;
send = "";
if (read <= 0 || read > write) {
System.out.println(read > 0 ? "recv msg:" + new String(recvByte, write, read - write, "UTF-8") : "");
if (read == 2) System.out.println("recv two data:" + (recvByte[0] & 0xff) + (recvByte[1] & 0xff));
Scanner sc = new Scanner(System. in );
send = sc.nextLine() + "\r\n";
// send=conIn.readLine()+"\r\n";
if ("exit".equals(send)) {
closeConnection(s, in, out);
return;
}
System.out.println("send msg :" + send);
ps.write(send.getBytes("ISO-8859-1"));
// ps.flush();
System.out.println("send over!");
}
ps.flush();
}
} catch(IOException e) {
System.out.println("Client Connected Failed :\t");
e.printStackTrace();
} catch(InterruptedException e) {
System.out.println("Thread Error!");
e.printStackTrace();
} finally {
closeConnection(s, in, out);
}
}
}
最近在写一个 telnet 客户端的代码,要求使用 socket 进行通讯而不是 apache 的工具包.遂本人在网上找了很多文档,结果发现和之前写的 socket 实时通讯的工具很像.于是我就毫不思索的将代码 copy 了一遍,结果运行时悲剧了.每次的 socket 连接自然没有问题,但是就是没有回应,我这边发送了数据,也没响应.
于是就郁闷了,本人是使用 windows 环境,telnet 虚拟机的 open solaris,可是不管怎么调试和修改,就是接受不到数据.没办法只能卡住了,把 telnet 协议和 socket 通讯又是一遍一遍的看,网上狂找文档,终于明白了问题的关键.socket 通讯可以实现客户端和服务器进行通讯和数据传输,比如 ftp,smtp 等都可以,但是对于 telnet 而言,telnet 时远程登陆的工具,它是跨平台的 (WINDOWSH,LINUX 等),因此在通讯时需要将数据和命令转换成双方约定好的格式(NVT,关于 NVT 这里不多讲,有个故事很形象的描述了这个问题).
其实最重要的是了解 telnet 登陆时的细节,telnet 在连接时,需要客户端和服务器进行协商,也就是双方规定发送数据的 "标准".
来源: http://lib.csdn.net/article/embeddeddevelopment/34567