Le Trung Thang, end of 2011
Telnet is a network protocol used on the Internet or local area networks to provide a bidirectional interactive text-oriented communications facility using a virtual terminal connection. User data is interspersed in-band with Telnet control information in an 8-bit byte oriented data connection over the Transmission Control Protocol (TCP) (soure: http://en.wikipedia.org/wiki/Telnet).
In Java, a good library for Telnet is Apache Commons Net (http://www.apache.org). As mentioned, Telnet is a bidirectional interactive protocol. So, when the client telnets to a host, it need wait for response from the host. This waiting time is significant that needs consider when you need read data from the host device. In the example following, we telnet to a host device which is a Impinj RFID reader, to login into the host machine. Whenever the host device receive a connection request from client, it will response to the client to request input the user and password with format of feedback message is "login: " and "Password: ".
package Test.Driver; import java.io.BufferedInputStream; import java.io.IOException; import java.io.PrintStream; import org.apache.commons.net.telnet.TelnetClient; public class LLRPmonitor { private TelnetClient telnet = new TelnetClient(); private BufferedInputStream input; private PrintStream output; // output stream private final int waitTime = 500; //wait time response from reader, in ms // =================================== public LLRPmonitor() { super(); } /** * Connect to reader * * @param userName * : The user name for login * @param password * : The password for login *@param IPReader * : IP address of reader * @return boolean. connect OK or Fail * @throws IOException * Any problems during connect * @author ThangLe */ private boolean connect(String IPReader, String userName, String password) { try { if (telnet != null && telnet.isConnected()) { telnet.disconnect(); } if (input != null) { input.close(); } if (output != null) { output.flush(); output.close(); } // Connect to the specified server telnet.setConnectTimeout(5000);// Timeout 5s telnet.connect(IPReader, 23); // Get input and output stream references input = new BufferedInputStream(telnet.getInputStream()); output = new PrintStream(telnet.getOutputStream()); Thread.sleep(waitTime); // wait for responding from reader // Log the user on if (readUntil("login: ") == null) return false; write(userName); Thread.sleep(waitTime); // wait for responding from reader if (readUntil("Password: ") == null) return false; write(password); Thread.sleep(waitTime); // wait for responding from reader // Advance to a prompt // readUntil(prompt + " "); return true; // connect OK } catch (Exception e) { e.printStackTrace(); return false; // connect fail } } // ================================ /* * */ private String readUntil(String pattern) { try { char lastChar = pattern.charAt(pattern.length() - 1); StringBuffer sb = new StringBuffer(); int numRead = 0; if(input.available()<= 5){//reader always returns more 5 chars return null; } char ch = (char) input.read(); while (true) { // System.out.print(ch); numRead++; sb.append(ch); if (ch == lastChar) { if (sb.toString().endsWith(pattern)) { return sb.toString(); } } if(input.available()==0){ break; } ch = (char) input.read(); if (numRead > 2000) { break; // can not read the pattern } } } catch (Exception e) { e.printStackTrace(); } return null; } // ================================= private void write(String value) { try { output.println(value); output.flush(); // System.out.println(value); } catch (Exception e) { e.printStackTrace(); } } // ================================== private void disconnect() { try { telnet.disconnect(); } catch (Exception e) { e.printStackTrace(); } } // ===================to Test================== public static void main(String[] args) { try { LLRPmonitor llrpMonitor = new LLRPmonitor(); llrpMonitor.connect("192.168.10.100","root","pass"); llrpMonitor.disconnect(); } catch (Exception e) { e.printStackTrace(); } } }
About logic, this code is correct. You opened a connection to device, send some commands to the host device and getting back the results from the host. However, when you run the program with a real device, maybe you are never able to log in to the host device. Why?
As you saw, Telnet is a bidirectional interactive protocol. So, when you send a command to host, there need a certain period of time to the host can send response back to the client. Depending of network speed, it can spend about a few hundred of milliseconds to the client can receive response message from the host. When you remove the line: Thread.sleep(waitTime), Program will be not waiting for this period of time, so you cannot receive response message which can be sent back later. Of course, you can replace Thread.sleep by the other ways.
The source code below is complete code to get LLRP status of Impinj RFID reader (www.impinj.com) by using Telnet command. The result receiving will be either ROSpec ACTIVE, INACTIVE or no existing ROSpec in reader.
package Test.Driver; import java.io.BufferedInputStream; import java.io.IOException; import java.io.PrintStream; import org.apache.commons.net.telnet.TelnetClient; public class LLRPmonitor { private TelnetClient telnet = new TelnetClient(); private BufferedInputStream input; private PrintStream output; // output stream // ========Tokens============= private final String promptMessRev = "LLRPAccessSpecCount"; private final String promptNumROS = "LLRPROSpecCount='"; private final String promptStatusROS = "LLRPROSpec1='"; private final int waitTime = 500; //wait time response from reader, in ms // =================================== public LLRPmonitor() { super(); } /** * Connect to reader * * @param userName * : The user name for login * @param password * : The password for login\ *@param IPReader * : IP address of reader * @return boolean. connect OK or Fail * @throws IOException * Any problems during connect * @author ThangLe */ private boolean connect(String IPReader, String userName, String password) { try { if (telnet != null && telnet.isConnected()) { telnet.disconnect(); } if (input != null) { input.close(); } if (output != null) { output.flush(); output.close(); } // Connect to the specified server telnet.setConnectTimeout(5000);// Timeout 5s telnet.connect(IPReader, 23); // Get input and output stream references input = new BufferedInputStream(telnet.getInputStream()); output = new PrintStream(telnet.getOutputStream()); Thread.sleep(waitTime); // wait for responding from reader // Log the user on if (readUntil("login: ") == null) return false; write(userName); Thread.sleep(waitTime); // wait for responding from reader if (readUntil("Password: ") == null) return false; write(password); Thread.sleep(waitTime); // wait for responding from reader // Advance to a prompt // readUntil(prompt + " "); return true; // connect OK } catch (Exception e) { e.printStackTrace(); return false; // connect fail } } /** * Check LLRP status * *@param IPReader * : IP address of reader * @return int: * 0: Has no the ROSPEC in reader. * 1: The ROSPEC is activating. * 2: The ROSPEC is inactive. * -1: A error occurred * @throws Exception * Any problems during connect * @author ThangLe */ public synchronized int checkROSPEC(String IPReader) { String ROstatus = ""; int index = 0; try { if (!connect(IPReader, "root", "impinj")) {//connect and login to reader return -1; // connect fail } // ================== ROstatus = sendCommand("show rfid llrp summary"); disconnect(); // stop connect to reader if (ROstatus == null) return -1; // Start processing received data from reader // ===============get number of the ROSPEC in reader==================== index = ROstatus.indexOf(promptNumROS); if (index != -1) { String NumROS = ROstatus.substring(index + 17, index + 18); // System.out.println(NumROS); if (NumROS.equals("0")) return 0; // has no ROSPEC in reader } // ==========get ROSPEC status========= index = ROstatus.indexOf(promptStatusROS); if (index != -1) { String statusROS = ROstatus.substring(index + 13, index + 19); // System.out.println(statusROS); if (statusROS.equals("Active")) return 1; // ROSPEC is Activated else return 2;// ROSPEC is Inactivated } } catch (Exception e) { e.printStackTrace(); return -1; } return -1; } // ================================ /* * */ private String readUntil(String pattern) { try { char lastChar = pattern.charAt(pattern.length() - 1); StringBuffer sb = new StringBuffer(); int numRead = 0; if(input.available()<= 5){//reader always returns more 5 chars return null; } char ch = (char) input.read(); while (true) { // System.out.print(ch); numRead++; sb.append(ch); if (ch == lastChar) { if (sb.toString().endsWith(pattern)) { return sb.toString(); } } if(input.available()==0){ break; } ch = (char) input.read(); if (numRead > 2000) { break; // can not read the pattern } } } catch (Exception e) { e.printStackTrace(); } return null; } // ================================= private void write(String value) { try { output.println(value); output.flush(); // System.out.println(value); } catch (Exception e) { e.printStackTrace(); } } // =================================== private String sendCommand(String command) { try { write(command); Thread.sleep(waitTime); // wait for responding from reader return readUntil(promptMessRev); } catch (Exception e) { e.printStackTrace(); } return null; } // ================================== private void disconnect() { try { telnet.disconnect(); } catch (Exception e) { e.printStackTrace(); } } // ===================to Test================== public static void main(String[] args) { try { LLRPmonitor llrpMonitor = new LLRPmonitor(); System.out.println(llrpMonitor.checkROSPEC("192.168.10.250")); } catch (Exception e) { e.printStackTrace(); } } }
Impinj Reader |
LLRP-ReaderInfo: checks RFID reader status (for LLRP protocol)
Download program
nice guide !
ReplyDeletewalk around on the internet, I found some guys already developed a few nice plug-in for eclipse:
+ with remote systems, we can explore the files on the server ( this plug-in use ftp, telnet, sctp to fetch files ). The image show the result of plug-in that I'm using:
http://i486.photobucket.com/albums/rr223/mathhoang/fpt_eclipse_mathhoang.png
+ to ssh into one server directly, there're a few plug-in to do that, but terminal plug-in is the good one I'm using:
http://i486.photobucket.com/albums/rr223/mathhoang/ssh_eclipse_mathhoang.png
Thanks Hoang,
ReplyDeleteWe use Eclipse plug-in in case of handle testing. If you want integrate it to your program, i think you should use libraries instead of plug-in. Right ?
Works Great, thanks.
ReplyDelete//catch the inputstream from device in a loop.
ReplyDeleteTelnetClient tc;
InputStream instr;
byte[] buff = new byte[60000000];
int ret_read = 0;
do {
instr = tc.getInputStream();
ret_read = instr.read(buff);
}while (ret_read ==0);
//catch the inputstream from device in a loop.
ReplyDeleteTelnetClient tc;
InputStream instr;
byte[] buff = new byte[60000000];
int ret_read = 0;
do {
instr = tc.getInputStream();
ret_read = instr.read(buff);
Thread.sleep(1000);
}while (ret_read ==0);
Thank you very much it helped a lot. Even in 2015 we still need the same code!
ReplyDeleteIt is power of Java. Write once, use forever :))
ReplyDeleteThank you! This will help me immensely.
ReplyDelete