【问题标题】:Automated Telnet client using commons-net使用 commons-net 的自动化 Telnet 客户端
【发布时间】:2016-08-01 15:31:31
【问题描述】:

我的要求是使用 java 程序通过 telnet 连接到某个服务器并运行一些命令并读取响应。根据这些响应,我需要执行一些操作

我与https://stackoverflow.com/a/1213188/1025328 合作

我正在使用 commons-net,我的程序是这样的:

public class TelnetSample {
    private TelnetClient telnet;
    private InputStream in;
    private PrintStream out;

    public TelnetSample(String server, int port) {
        try {
            // Connect to the specified server
            telnet = new TelnetClient();
            telnet.connect(server, port);

            in = telnet.getInputStream();
            out = new PrintStream(telnet.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String readResponse() {
        System.out.println("TelnetSample.readResponse()");

        StringBuilder out = new StringBuilder();

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            String line;
            while ((line = reader.readLine()) != null) {
                out.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println(out.toString());
        System.out.println("==========================================================");

        return out.toString();
    }

    public String read2() {
        System.out.println("TelnetSample.read()");

        StringBuffer sb = new StringBuffer();

        try {
            int available = in.available();

            for (int index = 0; index < available; index++) {
                char ch = (char) in.read();
                System.out.print(ch);
                sb.append(ch);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    public String sendCommand(String command) {
        try {
            InputStream is = new ByteArrayInputStream(command.getBytes());

            int ch;

            while ((ch = is.read()) != -1) {
                out.write(ch);
                out.flush();
            }

            System.out.println(command);

            String output = read2();

            if (output.trim().isEmpty()) {
                System.out.println("output empty");
            } else {
                System.out.println(output);
            }

            System.out.println("==========================================================");

            return output;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public void disconnect() {
        try {
            telnet.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        try {
            TelnetSample telnet = new TelnetSample("aspmx2.xxxxxx.com", 25);
            telnet.readResponse();

            telnet.sendCommand("Helo hi");
            telnet.sendCommand("mail from:xyz@testmail.com");
            telnet.sendCommand("rcpt to:pk@testmail.com");
            telnet.sendCommand("quit");

            telnet.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这里除了 telnet 连接响应之外,对于其他每个 sendCommand,我都得到一个空响应。有人能指出可能是什么问题吗?

我的输出是这样的

TelnetSample.readResponse()
220 mx.xxxxxx.com ESMTP o86si4086625pfi.217 - gsmtp
==========================================================
Helo hi
TelnetSample.read()
output empty
==========================================================
mail from:xyz@testmail.com
TelnetSample.read()
output empty
==========================================================
rcpt to:pk@testmail.com
TelnetSample.read()
output empty
==========================================================
quit
TelnetSample.read()
output empty
==========================================================

【问题讨论】:

    标签: java telnet apache-commons-net


    【解决方案1】:

    这段代码有几个问题:

    • 第一个问题在readResponse 方法中。当你使用 readLine() 您可以轻松阻止您的代码,并且将永远等待。请看讨论How to determine the exact state of a BufferedReader?
    • 第二个您不发送任何 CR/LF 字符。服务器像单行一样收到您的请求。例如:

    邮件从:xyz@testmail.comrcpt 到:pk@testmail.comquit

    要解决第一个问题,您可以选择多种方式:

    • 使用多线程模型
    • 使用 NIO API。我会为此推荐Netty。特别是对于您的情况,我可以看到您根本没有使用 Telnet 协议,而是连接到 SMTP 服务器。

    快速修复但最糟糕的是,等待服务器的第一行并继续:

    public String readResponse() {
        System.out.println("TelnetSmtpSample.readResponse()");
        StringBuilder out = new StringBuilder();
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            out.append(reader.readLine());
        } catch (Exception e) {
            e.printStackTrace();
        }
    
        System.out.println(out.toString());
        System.out.println("=====================");
    
        return out.toString();
    }
    

    修复第二个:

        telnet.sendCommand("Helo hi\r\n");
        telnet.sendCommand("mail from:xyz@testmail.com\r\n");
        telnet.sendCommand("rcpt to:pk@testmail.com\r\n");
        telnet.sendCommand("quit\r\n");
    

    【讨论】:

      【解决方案2】:

      read2 可能在实际返回数据之前从输入流中返回空值。试试这样的:

      private String read2() {
      
          StringBuffer sb = new StringBuffer();
      
          try {
              do {
                  if (in.available() > 0) {
                      char ch = (char) in.read();
                      sb.append(ch);
                  } else {
                      Thread.sleep(1000);
                  }
              } while (in.available()>0);
      
              String output = new String(sb);
              return output;
      
          } catch (Exception e) {
              e.printStackTrace();
          }
      
          return null;
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-07
        • 2014-04-17
        • 1970-01-01
        • 2011-03-31
        • 2019-08-12
        • 2012-07-08
        • 1970-01-01
        • 2011-02-07
        相关资源
        最近更新 更多