开发者

.read() throws intermittent SocketTimeoutException even though data should be there

开发者 https://www.devze.com 2023-03-24 19:55 出处:网络
I\'m working on a web server for Android and even though I\'ve spent days trying to fix it, I\'m at my wits\' end with this particular bug. I\'m trying to read the request from the browser, and the co

I'm working on a web server for Android and even though I've spent days trying to fix it, I'm at my wits' end with this particular bug. I'm trying to read the request from the browser, and the code works fine most of the time, but something like 5% of the requests fail and it throws random SocketTimeoutExceptions without even reading a single character from the Socket.

I have tested this with different browsers and it happens with all of them, so chances are the problem is on my end. Here's the relevant code, stripped down as far as possible:

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();
        }
    }
}
}

And:

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) {  }
    }

}
}

So ServerThread accepts the connection, HTTPSession tries to read from the Socket and sometimes it throws the SocketTimeoutException after the 15 seconds are up.

The output from the Log statement in the catch in this case is: Socket connected: true, Socket closed: false, InputShutDown: false

What gives? Surely 15 seconds is enough of a wait and it seems unlikely that mainstream web browsers just aren't sending any data, so why can't I read it?

I would appreciate any input on this problem.


SocketTimeoutException only means one thing: no data was available within the timeout period. So yes maybe your timeout is too short, and yes the browser didn't send it within the timeout period, or at least it didn't arrive at the server's socket receive buffer within the timeout period.

I would say 15 seconds is a bit aggressive for a server side timeout. 30s to a couple of minutes would be more like it.


I don't see any reason this code would fail in that way unless, like you said, a browser just wasn't sending anything. You could change the ips.read(); to System.out.println(ips.read()); to be sure of that. If you see a byte show up on stdout, then the browser did send something. My guess would be that in your full code, you're not properly recognizing the end of a request and continuing to wait for more data. After 15 seconds, you'll time out. But that's just a guess. If you post some code that demonstrates the problem, someone might be able to give you a definitive answer.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号