Telnet协议的实现

原创
2016/05/29 08:33
阅读数 1.8K

Telnet协议详解

rfc854.txt

java简单实现telnet协议(关键在于需解析telnet协议里的选项协商)

这里给大家推荐个网站,上面有各网络协议的中文版本,比如下面是Telnet协议和Socks V5协议

TELNET: http://www.cnpaf.net/rfc/rfc854.txt

SOCKS V5: http://www.cnpaf.net/rfc/rfc1928.txt

 

以下代码来自(http://shenxueliang.iteye.com/blog/1184553)

package telnet;
 
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
 
 
/**
 * Telnet简单实现
 * 
 * @author xueliang 2010.11.6
 * 
 */
public class Telnet {
	private static final byte SB = (byte) 250;// 子选项开始
	private static final byte SE = (byte) 240;// 子选项结束
	private static final byte WILL = (byte) 251;// 选项协商
	private static final byte WONT = (byte) 252;// 选项协商
	private static final byte DO = (byte) 253;// 选项协商
	private static final byte DONT = (byte) 254;// 选项协商
	private static final byte IAC = (byte) 255;// 数据字节255
	private static final byte ECHO = (byte) 1;// 回显
	private static final byte IS = (byte) 0;// 是
	private static final byte SUPPRESS = (byte) 3;// 抑制继续进行
	private static final byte TT = (byte) 24;// 终端类型
	private InputStream is;
	private OutputStream os;
	private Socket client;
	private byte[] readBuffer = new byte[1024];
 
	/**
	 * 打开telnet连接
	 * @param ip
	 * @param port 23
	 * @return
	 * @throws CmdException 
	 */
	public Telnet(String ip){
		this(ip, 23);
	}
 
	/**
	 * 打开telnet连接
	 * @param ip
	 * @param port
	 * @return
	 * @throws CmdException 
	 */
	public Telnet(String ip, int port){
		try {
			client = new Socket(ip, port);
			client.setSoTimeout(5000);//设置is的read方法阻塞时间为5秒
			is = client.getInputStream();
			os = client.getOutputStream();
		} catch (Exception e) {
			this.close();
		} 
	}
	/**
	 * 读取回显,并进行telnet协商
	 * @return
	 * @throws IOException
	 */
	public String recieveEcho() throws IOException {
		int len = is.read(this.readBuffer);
		if(is.available() == 0)
			return "";
		ArrayList<Byte> bsList = new ArrayList<Byte>();
		ArrayList<Byte> cmdList = new ArrayList<Byte>();
		for (int i = 0; i < len; i++) {
			int b = this.readBuffer[i] & 0xff;//&0xff是为了防止byte的255溢出,java中byte的取值是-128~127
			
if (b != 255) {//没有协商要求
				if (b == '\n' || b == '\0') {// NVT中行结束符以'\r\n'表示,回车以'\r\0表示'
					continue;
				}
				bsList.add((byte) b);
				continue;
			}
			cmdList.add(IAC); 
			switch (this.readBuffer[++i] & 0xff) {
			case 251:// 服务器想激活某选项
				if ((readBuffer[++i] & 0xff) == 1) {// 同意回显
					cmdList.add(DO);
					cmdList.add(ECHO);
				} else if ((readBuffer[i] & 0xff) == 3) {// 同意抑制继续执行
					cmdList.add(DO);
					cmdList.add(SUPPRESS);
					// cmdList.add(GA);
				} else {// 不同意其他类型协商
					cmdList.add(DONT);
					cmdList.add(readBuffer[i]);
				}
				break;
			case 253:// 服务器想让客户端发起激活某选项
				if ((readBuffer[++i] & 0xff) == 24) {// 终端类型
					cmdList.add(WONT);// 同意激活终端类型协商
					cmdList.add(TT);
				} else if ((readBuffer[i] & 0xff) == 1) {
					cmdList.add(WILL);
					cmdList.add(ECHO);
				} else {
					cmdList.add(WONT);// 不同意其他类型协商
					cmdList.add(readBuffer[i]);
				}
				break;
			case 250:// 子选项开始
				cmdList.add(SB);
				if ((readBuffer[++i] & 0xff) == 24
						&& (readBuffer[++i] & 0xff) == 1) {// 发送你的终端类型
					cmdList.add(TT);
					cmdList.add(IS);// 我的终端类型是
					cmdList.add((byte) 'V');
					cmdList.add((byte) 'T');
					cmdList.add((byte) '1');
					cmdList.add((byte) '0');
					cmdList.add((byte) '0');
				}
				break;
			case 240:// 子选项结束
				cmdList.add(SE);
				break;
			case 252:// 必须同意
				cmdList.add(DONT);
				cmdList.add(readBuffer[++i]);
				break;
			case 254:// 必须同意
				cmdList.add(WONT);
				cmdList.add(readBuffer[++i]);
				break;
			}
		}
		// 如果有协商则向服务端发送协商选项
		if (cmdList.size() > 0) {
			byte[] writeBuffer = new byte[cmdList.size()];
			for (int i = 0; i < cmdList.size(); i++) {
				writeBuffer[i] = cmdList.get(i);
			}
			os.write(writeBuffer);
		}
		// 组织回显字符
		int size = bsList.size();
		String str = "";
		if (size > 0) {
			byte[] bs = new byte[size];
			for (int i = 0; i < size; i++) {
				bs[i] = bsList.get(i).byteValue();
			}
			str = new String(bs, "gbk");
		}
		// 以下测试时打开
		// System.out.print("read===== ");
		// for (int i = 0; i < len; i++) {
		// System.out.print(readBuffer[i]&0xff);
		// System.out.print(" ");
		// }
		// System.out.println();
		// if(cmdList.size()>0){
		// System.out.print("write==== ");
		// for (int i = 0; i < cmdList.size(); i++) {
		// System.out.print(cmdList.get(i) & 0xff);
		// System.out.print(" ");
		// }
		// System.out.println();
		// }
		return str;
	}
 
	/**
	 * 直接发送命令,不发送回车键
	 * @param cmd
	 */
	public void sendWithoutCR(String cmd) {
		try {
			os.write(cmd.getBytes());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 命令中不要包括回车、换行
	 * @param cmd
	 */
	public void sendCmd(String cmd) {
		cmd += "\r\0";
		try {
			os.write(cmd.getBytes());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
 
	/**
	 * 按字节发送命令,数组中不要包括回车、换行
	 * @param cmd
	 */
	public void sendCmd(List<Byte> cmdList) {
		if(cmdList == null)return;
		int size = cmdList.size();
		byte[] send = null;
		if(cmdList.get(size-1) == '\r'){
			send = new byte[size+1];
			send[size] = '\0';
		}else{
			send = new byte[size];
		}
		for (int i = 0; i < size; i++) {
			send[i] = cmdList.get(i);
		}
		try {
			os.write(send);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
 
	/**
	 * 关闭telnet连接
	 */
	public void close() {
		if (is != null) {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if (os != null) {
			try {
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if (client != null) {
			try {
				client.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 读取期望值,使用默认超时时间15秒
	 * @param keyWords
	 * @return
	 */
	public String readKeyWords(String... keyWords){
		return this.readKeyWords(15000, keyWords);
	}
	/**
	 * 读取期望值
	 * @param timeOut 超时时间
	 * @param keyWords
	 * @return
	 * @throws CmdException 
	 */
	public String readKeyWords(long timeOut,String... keyWords){
		String rv = "";
		long nextTime = 0;
		long endTime = System.currentTimeMillis() + timeOut;
		do {
			try{
				String _rv = this.recieveEcho();
				rv += _rv;
			}catch(IOException e){
				nextTime = endTime - System.currentTimeMillis() ;
			}
		} while (!this.findKeyWord(keyWords, rv) && nextTime >= 0);
		if(nextTime < 0)
			System.err.println("Read TimeOut...Echo:\n"+rv);
		return rv;
	}
	
	/**
	 * 查找关键字
	 * @param keyWords
	 * @param str
	 * @return
	 */
	private boolean findKeyWord(String[] keyWords,String str){
		if(keyWords == null || str == null)return false;
		for (int i = 0; i < keyWords.length; i++) {
			if(str.indexOf(keyWords[i]) != -1)
				return true;
		}
		return false;
	}
	public static void main(String[] args) {
		Telnet telnet = new Telnet("10.110.111.193");
		String str = telnet.readKeyWords(":");
		System.out.println(str);
		telnet.sendCmd("boco");
		str = telnet.readKeyWords(":");
		telnet.sendCmd("Ab123456");
		str = telnet.readKeyWords("$");
		System.out.println(str);
		telnet.sendCmd("ls");
		str = telnet.readKeyWords(10000,"$");
		System.out.println(str);
		telnet.close();
	}
}

 

 

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部