• 关于telnet协议的研究以及用java进行封装实现自己的telnet客户端(转)


    最近在做一个远程控制的模块,其中用到了telnet协议,开始用的是apache-net包的telnetclient,但发现问题不少,比较慢,还有就是判断是否read完毕的问题。后来经过讨论打算实现自己的telnet,于是网址打罗了一番,找了一个,但是bug也不少,就开始封装。具体的telnet我已经发过2篇文章了,这里再发布一个深化封装的telnet实现。

    仅供参考,可以在windows和linux上运行。

    1. package baby.net.base;  
    2.   
    3. import java.io.IOException;  
    4. import java.io.InputStream;  
    5. import java.io.OutputStream;  
    6. import java.net.InetSocketAddress;  
    7. import java.net.Socket;  
    8. import java.util.ArrayList;  
    9.   
    10. import org.apache.log4j.Logger;  
    11.   
    12. /** 
    13.  * telnet 基本连接类 
    14.  *  
    15.  * @description 
    16.  * @author weichaofan 
    17.  * @date 2013年10月25日 
    18.  */  
    19. public class TelnetBase {  
    20.     private static final byte SB = (byte) 250;// 子选项开始   
    21.     private static final byte SE = (byte) 240;// 子选项结束   
    22.     private static final byte WILL = (byte) 251;// 选项协商   
    23.     private static final byte WONT = (byte) 252;// 选项协商   
    24.     private static final byte DO = (byte) 253;// 选项协商   
    25.     private static final byte DONT = (byte) 254;// 选项协商   
    26.     private static final byte IAC = (byte) 255;// 数据字节255   
    27.     private static final byte ECHO = (byte) 1;// 回显   
    28.     private static final byte IS = (byte) 0;// 是   
    29.     private static final byte SUPPRESS = (byte) 3;// 抑制继续进行   
    30.     private static final byte TT = (byte) 24;// 终端类型   
    31.     private InputStream is;  
    32.     private OutputStream os;  
    33.     private Socket client;  
    34.     private byte[] readBuffer = new byte[20 * 1024];  
    35.     private int miniReadIntervalMillSec = 3000;// 最短read阻塞间隔时间-毫秒   
    36.     private int connectTimeout = 1000;// 连接超时时间   
    37.     private int maxReadTimeout = 5000;  
    38.   
    39.     public static String[] failTags = { "Failed", "fail", "incorrect" };  
    40.     public static String[] loginTags = { "$", "#", ">", "ogin", "@" };  
    41.     public static String[] commondEndTags= { "$", "#", ">"};  
    42.     public static String[] allTags = { "Failed", "fail", "incorrect", "$", "#",  
    43.             ">", "ogin", "@" };  
    44.   
    45.     private String ip;  
    46.     private int port = 23;  
    47.   
    48.     Logger logger = Logger.getLogger(getClass());  
    49.   
    50.     /** 
    51.      *  
    52.      * 打开telnet连接 
    53.      *  
    54.      * @param ip 
    55.      * @param port 
    56.      *            23 
    57.      *  
    58.      * @return 
    59.      *  
    60.      * @throws CmdException 
    61.      */  
    62.   
    63.     public TelnetBase(String ip) {  
    64.   
    65.         this(ip, 23);  
    66.   
    67.     }  
    68.   
    69.     /** 
    70.      *  
    71.      * 打开telnet连接 
    72.      *  
    73.      * @param ip 
    74.      * @param port 
    75.      * @return 
    76.      * @throws CmdException 
    77.      */  
    78.   
    79.     public TelnetBase(String ip, int port) {  
    80.         this.ip = ip;  
    81.         this.port = port;  
    82.     }  
    83.   
    84.     /** 
    85.      * 连接 
    86.      *  
    87.      * @return 
    88.      * @throws Exception 
    89.      */  
    90.     public String connect() throws Exception {  
    91.         try {  
    92.   
    93.             client = new Socket();  
    94.             client.connect(new InetSocketAddress(ip, port), connectTimeout);  
    95.             client.setSoTimeout(miniReadIntervalMillSec);// 设置is的read方法阻塞时间   
    96.             is = client.getInputStream();  
    97.             os = client.getOutputStream();  
    98.         } catch (Exception e) {  
    99.             this.close();  
    100.             throw new Exception(e);  
    101.         }  
    102.         return readKeyWords("ogin:");  
    103.     }  
    104.   
    105.     /** 
    106.      *  
    107.      * 读取回显,并进行telnet协商 
    108.      *  
    109.      * @return 
    110.      *  
    111.      * @throws IOException 
    112.      */  
    113.   
    114.     public String recieveEcho() throws IOException {  
    115.   
    116.         int len = is.read(this.readBuffer);  
    117.   
    118.         ArrayList<Byte> bsList = new ArrayList<Byte>();  
    119.         ArrayList<Byte> cmdList = new ArrayList<Byte>();  
    120.         for (int i = 0; i < len; i++) {  
    121.             int b = this.readBuffer[i] & 0xff;// &0xff是为了防止byte的255溢出,java中byte的取值是-128~127   
    122.             if (b != 255) {  
    123.                 if (b == ' ' || b == '') {// NVT中行结束符以' '表示,回车以' 表示'   
    124.                     continue;  
    125.                 }  
    126.                 bsList.add((byte) b);  
    127.                 continue;  
    128.             }  
    129.             cmdList.add(IAC);  
    130.             switch (this.readBuffer[++i] & 0xff) {  
    131.             case 251:// 服务器想激活某选项   
    132.                 if ((readBuffer[++i] & 0xff) == 1) {// 同意回显   
    133.                     cmdList.add(DO);  
    134.                     cmdList.add(ECHO);  
    135.                 } else if ((readBuffer[i] & 0xff) == 3) {// 同意抑制继续执行   
    136.                     cmdList.add(DO);  
    137.                     cmdList.add(SUPPRESS);  
    138.                     // cmdList.add(GA);   
    139.                 } else {// 不同意其他类型协商   
    140.                     cmdList.add(DONT);  
    141.                     cmdList.add(readBuffer[i]);  
    142.                 }  
    143.                 break;  
    144.             case 253:// 服务器想让客户端发起激活某选项   
    145.                 if ((readBuffer[++i] & 0xff) == 24) {// 终端类型   
    146.                     cmdList.add(WONT);// 同意激活终端类型协商   
    147.                     cmdList.add(TT);  
    148.                 } else if ((readBuffer[i] & 0xff) == 1) {  
    149.                     cmdList.add(WILL);  
    150.                     cmdList.add(ECHO);  
    151.                 } else {  
    152.                     cmdList.add(WONT);// 不同意其他类型协商   
    153.                     cmdList.add(readBuffer[i]);  
    154.                 }  
    155.                 break;  
    156.             case 250:// 子选项开始   
    157.                 cmdList.add(SB);  
    158.                 if ((readBuffer[++i] & 0xff) == 24  
    159.                         && (readBuffer[++i] & 0xff) == 1) {// 发送你的终端类型   
    160.                     cmdList.add(TT);  
    161.                     cmdList.add(IS);// 我的终端类型是   
    162.                     cmdList.add((byte) 'V');  
    163.                     cmdList.add((byte) 'T');  
    164.                     cmdList.add((byte) '1');  
    165.                     cmdList.add((byte) '0');  
    166.                     cmdList.add((byte) '0');  
    167.                 }  
    168.                 break;  
    169.             case 240:// 子选项结束   
    170.                 cmdList.add(SE);  
    171.                 break;  
    172.             case 252:// 必须同意   
    173.                 cmdList.add(DONT);  
    174.                 cmdList.add(readBuffer[++i]);  
    175.                 break;  
    176.             case 254:// 必须同意   
    177.                 cmdList.add(WONT);  
    178.                 cmdList.add(readBuffer[++i]);  
    179.                 break;  
    180.             }  
    181.         }  
    182.         // 如果有协商则向服务端发送协商选项   
    183.         if (cmdList.size() > 0) {  
    184.             byte[] writeBuffer = new byte[cmdList.size()];  
    185.             for (int i = 0; i < cmdList.size(); i++) {  
    186.                 writeBuffer[i] = cmdList.get(i);  
    187.             }  
    188.             os.write(writeBuffer);  
    189.         }  
    190.   
    191.         // 组织回显字符   
    192.         int size = bsList.size();  
    193.         String str = "";  
    194.         if (size > 0) {  
    195.             byte[] bs = new byte[size];  
    196.             for (int i = 0; i < size; i++) {  
    197.                 bs[i] = bsList.get(i).byteValue();  
    198.             }  
    199.             str = new String(bs, "gbk");  
    200.         } else {  
    201.             // 如果是协商,则回传协商信息   
    202.             if (cmdList.size() > 0) {  
    203.                 str = recieveEcho();  
    204.             }  
    205.         }  
    206.     //  log(len, cmdList);   
    207.         return str;  
    208.     }  
    209.   
    210.     private void log(int len, ArrayList<Byte> cmdList) {  
    211.         logger.debug("read===== ");  
    212.         for (int i = 0; i < len; i++) {  
    213.             logger.debug(readBuffer[i] & 0xff);  
    214.             logger.debug(" ");  
    215.         }  
    216.   
    217.         if (cmdList.size() > 0) {  
    218.             logger.debug("write==== ");  
    219.             for (int i = 0; i < cmdList.size(); i++) {  
    220.                 logger.debug(cmdList.get(i) & 0xff);  
    221.                 logger.debug(" ");  
    222.             }  
    223.   
    224.         }  
    225.     }  
    226.   
    227.     /** 
    228.      * 用户名 命令中不要包括回车、换行 
    229.      *  
    230.      * @param cmd 
    231.      * @param keyWords 
    232.      * @return 
    233.      */  
    234.     public String sendUserName(String name) throws Exception {  
    235.         name += " ";  
    236.         os.write(name.getBytes());  
    237.   
    238.         return readKeyWords("assword");  
    239.     }  
    240.   
    241.     /** 
    242.      * 密码 命令中不要包括回车、换行 
    243.      *  
    244.      * @param cmd 
    245.      * @param keyWords 
    246.      * @return 
    247.      */  
    248.     public String sendUserPwd(String pwd) throws Exception {  
    249.         pwd += " ";  
    250.         os.write(pwd.getBytes());  
    251.   
    252.         return readKeyWords(allTags);  
    253.     }  
    254.   
    255.     /** 
    256.      * 命令中不要包括回车、换行 
    257.      *  
    258.      * @param cmd 
    259.      * @param keyWords 
    260.      * @return 
    261.      */  
    262.     public String sendCmd(String cmd, String... keyWords) throws Exception {  
    263.           
    264.         return sendCmd(cmd,false,keyWords);  
    265.     }  
    266.     /** 
    267.      * 命令中不要包括回车、换行 
    268.      *  
    269.      * @param cmd 
    270.      * @param keyWords 
    271.      * @return 
    272.      */  
    273.     public String sendCmd(String cmd,boolean excludeCommandCheck, String... keyWords) throws Exception {  
    274.         os.write((cmd + " ").getBytes());  
    275.           
    276.         if(!excludeCommandCheck){  
    277.             return readKeyWords(cmd,maxReadTimeout,keyWords);  
    278.         }else{  
    279.             return readKeyWords(keyWords);  
    280.         }  
    281.     }  
    282.   
    283.     /** 
    284.      * 命令中不要包括回车、换行 默认搜索条件为$、#、> 
    285.      *  不包含执行命令中的关键字 
    286.      * @param cmd 
    287.      * @param keyWords 
    288.      * @return 
    289.      */  
    290.     public String sendCommand(String cmd) throws Exception {  
    291.   
    292.         return sendCommand(cmd,false);  
    293.     }  
    294.     /** 
    295.      * 命令中不要包括回车、换行 默认搜索条件为$、#、> 
    296.      *  是否包含执行命令中的关键字 
    297.      * @param cmd 
    298.      * @param keyWords 
    299.      * @return 
    300.      */  
    301.     public String sendCommand(String cmd,boolean excludeCommandCheck) throws Exception {  
    302.           
    303.         os.write((cmd + " ").getBytes());  
    304.         if(!excludeCommandCheck){  
    305.             return readKeyWords(cmd,maxReadTimeout,commondEndTags);  
    306.         }else{  
    307.             return readKeyWords(commondEndTags);  
    308.         }  
    309.     }  
    310.   
    311.     /** 
    312.      * 命令中不要包括回车、换行 默认搜索条件为$、#、> 
    313.      * 不包含执行命令中的关键字 
    314.      * @param cmd 
    315.      * @param timeOut 
    316.      * @param keyWords 
    317.      * @return 
    318.      */  
    319.     public String sendCommand(String cmd, long timeOut) throws Exception {  
    320.           
    321.         return sendCommand(cmd,timeOut, false);  
    322.     }  
    323.     /** 
    324.      * 命令中不要包括回车、换行 默认搜索条件为$、#、> 
    325.      * 是否包含执行命令中的关键字 
    326.      * @param cmd 
    327.      * @param timeOut 
    328.      * @param keyWords 
    329.      * @return 
    330.      */  
    331.     public String sendCommand(String cmd, long timeOut,boolean excludeCommandCheck) throws Exception {  
    332.         os.write((cmd + " ").getBytes());  
    333.           
    334.         if(!excludeCommandCheck){  
    335.             return readKeyWords(cmd,timeOut, commondEndTags);  
    336.         }else{  
    337.             return readKeyWords(timeOut, commondEndTags);  
    338.         }  
    339.           
    340.     }  
    341.   
    342.     /** 
    343.      * 命令中不要包括回车、换行 
    344.      *  
    345.      * @param cmd 
    346.      * @param timeOut 
    347.      * @param keyWords 
    348.      * @return 
    349.      */  
    350.     public String sendCmd(String cmd, long timeOut, String... keyWords)  
    351.             throws Exception {  
    352.           
    353.         return sendCmd(cmd,false,timeOut, keyWords);  
    354.     }  
    355.     /** 
    356.      * 命令中不要包括回车、换行 
    357.      *  
    358.      * @param cmd 
    359.      * @param timeOut 
    360.      * @param keyWords 
    361.      * @return 
    362.      */  
    363.     public String sendCmd(String cmd, boolean excludeCommandCheck,long timeOut, String... keyWords)  
    364.             throws Exception {  
    365.         os.write((cmd + " ").getBytes());  
    366.         if(!excludeCommandCheck){  
    367.             return readKeyWords(cmd,timeOut, keyWords);  
    368.         }else{  
    369.             return readKeyWords(timeOut, keyWords);  
    370.         }  
    371.           
    372.     }  
    373.   
    374.     /** 
    375.      *  
    376.      * 关闭telnet连接 
    377.      */  
    378.   
    379.     public void close() {  
    380.         if (is != null) {  
    381.             try {  
    382.                 is.close();  
    383.             } catch (IOException e) {  
    384.                 e.printStackTrace();  
    385.             }  
    386.         }  
    387.         if (os != null) {  
    388.             try {  
    389.                 os.close();  
    390.             } catch (IOException e) {  
    391.                 e.printStackTrace();  
    392.             }  
    393.         }  
    394.         if (client != null) {  
    395.             try {  
    396.                 client.close();  
    397.             } catch (IOException e) {  
    398.                 e.printStackTrace();  
    399.             }  
    400.         }  
    401.     }  
    402.   
    403.     /** 
    404.      *  
    405.      * 读取期望值,使用默认超时时间5秒 
    406.      *  
    407.      * @param keyWords 
    408.      *  
    409.      * @return 
    410.      */  
    411.   
    412.     public String readKeyWords(String... keyWords) {  
    413.   
    414.         return this.readKeyWords(maxReadTimeout, keyWords);  
    415.   
    416.     }  
    417.   
    418.     /** 
    419.      *  
    420.      * 读取期望值 
    421.      *  
    422.      * @param timeOut 
    423.      *            超时时间 
    424.      *  
    425.      * @param keyWords 
    426.      *  
    427.      * @return 
    428.      *  
    429.      * @throws CmdException 
    430.      */  
    431.   
    432.     public String readKeyWords(long timeOut, String... keyWords) {  
    433.         String rv = "";  
    434.         long nextTime = 0;  
    435.         long endTime = System.currentTimeMillis() + timeOut;  
    436.         do {  
    437.             try {  
    438.                 String _rv = this.recieveEcho();  
    439.                 rv += _rv;  
    440.             } catch (IOException e) {  
    441.   
    442.                 nextTime = endTime - System.currentTimeMillis();  
    443.             }  
    444.         } while (!this.findKeyWord(keyWords, rv) && nextTime >= 0);  
    445.         if (nextTime < 0)  
    446.             System.err.println("Read TimeOut...Echo: " + rv);  
    447.         return rv;  
    448.   
    449.     }  
    450.     /** 
    451.      *  
    452.      * 读取期望值  排除command中含有的关键字 
    453.      *  
    454.      * @param timeOut 
    455.      *            超时时间 
    456.      *  
    457.      * @param keyWords 
    458.      *  
    459.      * @return 
    460.      *  
    461.      * @throws CmdException 
    462.      */  
    463.       
    464.     public String readKeyWords(String command,long timeOut, String... keyWords) {  
    465.         String rv = "";  
    466.         long nextTime = 0;  
    467.         long endTime = System.currentTimeMillis() + timeOut;  
    468.         do {  
    469.             try {  
    470.                 String _rv = this.recieveEcho();  
    471.                 rv += _rv;  
    472.             } catch (IOException e) {  
    473.                   
    474.                 nextTime = endTime - System.currentTimeMillis();  
    475.             }  
    476.         } while (!this.findKeyWord(command,keyWords, rv) && nextTime >= 0);  
    477.         if (nextTime < 0)  
    478.             System.err.println("Read TimeOut...Echo: " + rv);  
    479.         return rv;  
    480.           
    481.     }  
    482.   
    483.     /** 
    484.      *  
    485.      * 查找关键字 
    486.      *  
    487.      * @param keyWords 
    488.      *  
    489.      * @param str 
    490.      *  
    491.      * @return 
    492.      */  
    493.   
    494.     public boolean findKeyWord(String[] keyWords, String str) {  
    495.         if (str == null || "".equals(str))  
    496.             return false;  
    497.         if (keyWords == null || keyWords.length == 0)  
    498.             return true;  
    499.         for (int i = 0; i < keyWords.length; i++) {  
    500.             if (str.indexOf(keyWords[i]) != -1)  
    501.                 return true;  
    502.         }  
    503.         return false;  
    504.     }  
    505.     /** 
    506.      *  
    507.      * 查找关键字  排除command中含有的关键字 
    508.      *  
    509.      * @param keyWords 
    510.      *  
    511.      * @param str 
    512.      *  
    513.      * @return 
    514.      */  
    515.       
    516.     public boolean findKeyWord(String command,String[] keyWords, String str) {  
    517.         if (str == null || "".equals(str))  
    518.             return false;  
    519.         if (keyWords == null || keyWords.length == 0)  
    520.             return true;  
    521.         System.out.println(str);  
    522.         if(-1 != str.indexOf(command)){  
    523.             str=str.substring(str.indexOf(command)+command.length());  
    524.             for (int i = 0; i < keyWords.length; i++) {  
    525.                 if (str.indexOf(keyWords[i]) != -1)  
    526.                     return true;  
    527.             }  
    528.         }  
    529.           
    530.           
    531.         return false;  
    532.     }  
    533.   
    534.     /** 
    535.      * 最短读阻塞时间 
    536.      *  
    537.      * @return 
    538.      */  
    539.     public int getMiniReadIntervalMillSec() {  
    540.         return miniReadIntervalMillSec;  
    541.     }  
    542.   
    543.     public void setMiniReadIntervalMillSec(int miniReadIntervalMillSec) {  
    544.         this.miniReadIntervalMillSec = miniReadIntervalMillSec;  
    545.     }  
    546.   
    547.     /** 
    548.      * 连接超时时间 
    549.      *  
    550.      * @return 
    551.      */  
    552.     public int getConnectTimeout() {  
    553.         return connectTimeout;  
    554.     }  
    555.   
    556.     public void setConnectTimeout(int connectTimeout) {  
    557.         this.connectTimeout = connectTimeout;  
    558.     }  
    559.   
    560.     /** 
    561.      * 最大读阻塞时间 
    562.      *  
    563.      * @return 
    564.      */  
    565.     public int getMaxReadTimeout() {  
    566.         return maxReadTimeout;  
    567.     }  
    568.   
    569.     public void setMaxReadTimeout(int maxReadTimeout) {  
    570.         this.maxReadTimeout = maxReadTimeout;  
    571.     }  
    572.   
    573. }

    http://blog.csdn.net/chaofanwei/article/details/14130179

    http://www.iteye.com/topic/284636

  • 相关阅读:
    Android组件化/模块化开发(一)
    Android Intent用法总结
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1101:不定方程求解
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1094:与7无关的数
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1094:与7无关的数
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1094:与7无关的数
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1093:计算多项式的值
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1093:计算多项式的值
    信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1093:计算多项式的值
    1096:数字统计
  • 原文地址:https://www.cnblogs.com/softidea/p/4553665.html
Copyright © 2020-2023  润新知