今天测试telnet登陆遇到一个奇怪的问题:
加入while (in.available() > 0) {} 判断时,谁在方法in.available()时阻塞。请教各位大神,available方法本身不是个阻塞的方法,在什么情况下会出现这样的问题?
private boolean waitForLoginFinish() throws IOException
{
StringBuffer sb = new StringBuffer();
char ch;
    long start=System.currentTimeMillis() ;
    System.out.println("start start");
        while(System.currentTimeMillis() - start < timeout){
        
         int i = -1;
         while (in.available() >= 0) {
         //long s=System.currentTimeMillis() ;
         //while(System.currentTimeMillis() - s < 10000){
             i=in.read();
             if(i == -1) {
             return false;
             }
             ch = (char) i;
             sb.append(ch);
             System.out.println(sb.toString());
             if (sb.indexOf(prompt) != -1) {
             return true;
     }else if(sb.indexOf(env.getLoginSuccPrompt())!=-1){
     return false;
     }else {
     try {
     //这里是防止网络慢的时候,in.available()经常为0,导致大量循环引起过多的indexOf
     Thread.sleep(100);
     } catch (Exception e) {}
     }
}
         System.out.println("end read");
        }
        return false;
如下为输入结果,如果将
while (in.available() >= 0) {
替换为:
long s=System.currentTimeMillis() ;
while(System.currentTimeMillis() - s < 10000){
就没有问题,另外,有没有好的方法可以解决read阻塞的问题.......start start
+
++
+++
lgi:op="EMS\\xxxxxx",pwd="xxxxx!";
invoke arguments,taskId:groovy
com.eastcom.dcmp.probe.common.exception.SessionException: Login failed ! [xxxxxxxxxxxxxxx] , reason :Read timed out
at com.eastcom.dcmp.probe.terminal.sessionImpl.TL2Session.login(TL2Session.java:205)
at com.eastcom.dcmp.probe.common.collect.BaseCollector.loginSession(BaseCollector.java:56)
at com.eastcom.dcmp.script.TaskGroovyExecutor.execute(TaskGroovyExecutor.java:59)
at com.eastcom.dcmp.script.test.TestTerminalGroovy.testGroovy5(TestTerminalGroovy.java:62)
at com.eastcom.dcmp.script.test.TestTerminalGroovy.testGroovy(TestTerminalGroovy.java:25)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

解决方案 »

  1.   

    while (in.available() > 0)
    等于0,就应该跳出循环了吧
      

  2.   


    哥,不是很懂,但是你要对流进行操作就修改流的读取方法吧,我能想到的,才学习到流这里,要想除掉=0时候还要循环一次才出来-1的话,只能写自己的流读取方法。教程给的草例:
    public class MyOwnStream2 extends InputStream
    {
    protected byte[] data; protected int ptr = 0;// 读取到的位置 private int  = 0;// 标记位置 public MyOwnStream2(byte[] b)
    {
    this.data = b;
    } @Override
    public int read() throws IOException
    {
    return ptr < data.length ? data[ptr++] : -1;
    } @Override
    public int read(byte[] b, int off, int len) throws IOException
    {
    if (this.ptr >= data.length || len < 0)
    {
    return -1;
    } if (this.ptr + len > data.length)
    {
    len = data.length - this.ptr;
    } if (len == 0)
    {
    return 0;
    } System.arraycopy(data, ptr, b, off, len); ptr += len; return len;
    } /**
     * 剩余未读的长度
     */
    @Override
    public int available() throws IOException
    {
    return data.length - ptr;
    } /**
     * 关闭,简单实现使读取位置等于文件长度
     */
    @Override
    public void close() throws IOException
    {
    ptr = data.length;
    } /**
     * 标记位置,下次可以跳到这个位置
     */
    @Override
    public synchronized void (int readlimit)
    {
    this. = readlimit;
    } /**
     * 跳回标记位置
     */
    @Override
    public synchronized void reset() throws IOException
    {
    if ( < 0 ||  > data.length)
    {
    throw new IOException("the position is not valid");
    }
    ptr = ;
    } /**
     * 是否支持标记,这里强制可以
     */
    @Override
    public boolean Supported()
    {
    return true;
    }}