即使数据存在,.read()也会抛出间歇性的SocketTimeoutException

时间:2011-08-03 17:29:24

标签: java android multithreading sockets

我正在开发一款适用于Android的网络服务器,即使我花了好几天时间尝试修复它,但我仍然对这个特定的错误感到满意。我正在尝试从浏览器中读取请求,并且代码在大多数情况下都能正常工作,但是有5%的请求会失败并且它会抛出随机的SocketTimeoutExceptions,甚至不会从Socket中读取单个字符。

我已经用不同的浏览器对它进行了测试,并且它发生在所有这些浏览器上,所以很有可能问题出在我的最后。这是相关的代码,尽可能地删除:

public class ServerThread extends Thread {

private ServerSocket ss = null;
private boolean isRunning;

private ExecutorService threadPool = new ThreadPoolExecutor(2, 12,
          60L, TimeUnit.SECONDS,
          new SynchronousQueue<Runnable>(),
          Executors.defaultThreadFactory(), 
          new ThreadPoolExecutor.CallerRunsPolicy());

public ServerThread() {
}

public synchronized void run() {
    ss = new ServerSocket(8080, 1);
    isRunning = true;

    while (isRunning) {
        Socket clientSocket = null;

        try {
            if (ss != null) {
                clientSocket = ss.accept();
                if (isRunning) {
                    this.threadPool.execute(new HTTPSession(clientSocket));
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
}

public class HTTPSession implements Runnable {

private Socket mSocket = null;

public HTTPSession (Socket s) {
    mSocket = s;
}


public void run() {

    InputStream ips = null;

    try {
        mSocket.setSoTimeout(15000);
        ips = mSocket.getInputStream();
        ips.read();
    }
    catch (Exception e) {
        e.printStackTrace();
        Log.v("HTTPSession", "Socket connected: " + mSocket.isConnected() + ", Socket closed: " + mSocket.isClosed() + ", InputShutdown: " + mSocket.isInputShutdown());
    }
    finally {
            try { ips.close(); } catch (IOException ioe) {  }
            try { mSocket.close(); } catch (IOException ioe) {  }
    }

}
}

所以ServerThread接受连接,HTTPSession尝试从Socket读取,有时它会在15秒后启动SocketTimeoutException。

在这种情况下,catch中Log语句的输出是:     Socket connected:true,Socket closed:false,InputShutDown:false

是什么给出的?当然15秒就足够了,主流网络浏览器似乎不太可能不发送任何数据,为什么我不能读它呢?

我很感激有关此问题的任何意见。

2 个答案:

答案 0 :(得分:1)

SocketTimeoutException仅表示一件事:在超时期限内没有可用的数据。所以是的,也许你的超时时间太短,是的,浏览器没有在超时期限内发送,或者至少在超时期限内没有到达服务器的套接字接收缓冲区。

我想说服务器端超时15秒有点激进。 30秒到几分钟会更像它。

答案 1 :(得分:0)

我认为这个代码没有任何理由以这种方式失败,除非像你说的那样,浏览器只是没有发送任何内容。您可以将ips.read();更改为System.out.println(ips.read());以确保这一点。如果你看到一个字节出现在stdout上,那么浏览器确实发送了一些东西。我的猜测是,在您的完整代码中,您没有正确识别请求的结束并继续等待更多数据。 15秒后,你会超时。但这只是猜测。如果您发布一些演示此问题的代码,则有人可能会给您一个明确的答案。