Java主线程没有为ServerSocket接受唤醒

时间:2015-01-31 21:48:57

标签: java multithreading sockets http

我正在使用java创建一个简单的Web代理应用程序。基本上,main方法创建一个RequestReceiver对象,该对象具有监听Web浏览器http请求的ServerSocket。从serverSocket.accept()返回的套接字创建一个新的Connection对象,并将其放入一个线程池中。

我遇到的问题是并非所有的http GET请求似乎都被serverSocket接收。例如,在我正在测试的一个网页上,我可以看到代理服务器只收到了10个GET请求中的7个。这会导致网页挂起并需要很长时间才能加载。什么可能导致带有serverSocket.accept()函数的线程在建立新连接时不总是优先执行?

RequestReceiver.java

public class RequestReceiver {
    public static final int LISTENING_PORT = 4000;
    public static final int CONNECTION_THREAD_POOL_SIZE = 30;

    private ServerSocket serverSocket;
    private ThreadPoolExecutor connectionThreads;

    public RequestReceiver() throws IOException{
        serverSocket = new ServerSocket(LISTENING_PORT);
        connectionThreads = new ThreadPoolExecutor(CONNECTION_THREAD_POOL_SIZE, CONNECTION_THREAD_POOL_SIZE, 
                1000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
    }

    public void start(){
        try {
            System.out.println("Current Pool Size: " + connectionThreads.getPoolSize() 
                    + " Active threads: " + connectionThreads.getActiveCount() );
            Connection conn = new Connection(serverSocket.accept());
            System.out.println("Created a new connection thread. Request from " + conn.clientSocketToString());
            connectionThreads.execute(conn);
        } catch (IOException e) {
            System.err.println("Exception occured when accepting a new connection.");
            e.printStackTrace();
        }
    }
}

Connection.java

public class Connection implements Runnable{

public static final int REPLY_CHUNK_SIZE = 32768;
public static final int DEFAULT_WEB_SERVER_PORT = 80;
public static final int SERVER_SOCKET_TIMEOUT = 0; // milliseconds
public static final int CLIENT_SOCKET_TIMEOUT = 0; // milliseconds

private Socket clientSocket, serverSocket;
private InputStream clientIS, serverIS;
private OutputStream clientOS, serverOS;

public Connection(Socket clientSocket){
    this.clientSocket = clientSocket;
    // set client socket timeout
    try{
        clientSocket.setSoTimeout(CLIENT_SOCKET_TIMEOUT);
    }catch(SocketException soe){
        soe.printStackTrace();
    }
}

@Override
public void run() {
    String connection = "";
    try{
        // setup client streams
        clientIS = clientSocket.getInputStream();
        clientOS = clientSocket.getOutputStream();
        // get the request from the browser
        String request = "";
        String hostname = "";
        String[] hostAndPort = new String[2];
        request = browserInputStreamToString(clientIS);
        hostname = getHostName(request);
        hostAndPort = hostname.split(":");
        connection = "Connection to: " + hostname + " from " + clientSocket.getInetAddress().getHostName() 
                + ":" + clientSocket.getPort() + " Request: " + request.split(System.getProperty("line.separator"))[0];
        System.out.println("OPENED>> " + connection);
        // Attempt to create socket to server
        serverSocket = new Socket(hostAndPort[0], (hostAndPort.length > 1 ? new Integer(hostAndPort[1]):DEFAULT_WEB_SERVER_PORT));
        // set timeout
        serverSocket.setSoTimeout(SERVER_SOCKET_TIMEOUT);
        // Set up server streams
        serverIS = serverSocket.getInputStream();
        serverOS = serverSocket.getOutputStream();
        // send client request to server
        serverOS.write(request.getBytes());
        serverOS.flush();
        // send server response to client in chunks
        byte[] reply = new byte[REPLY_CHUNK_SIZE];
        int replyLength = serverIS.read(reply);
        while( replyLength != -1 ){
            clientOS.write(reply, 0, replyLength);
            clientOS.flush();
            replyLength = serverIS.read(reply);
        }
        // close sockets
        clientSocket.close();
        serverSocket.close();
    }catch(Exception e){
        e.printStackTrace();
    } finally{
        try {
            if(clientSocket != null){
                clientSocket.close();
            }
            if(serverSocket != null){
                serverSocket.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    System.out.println("CLOSED>> " + connection);
}

编辑:从catch语句中删除了return语句

1 个答案:

答案 0 :(得分:0)

当你说10分中的7分时,你的意思是你测试了10次或者几次并得到了这个速度?我问,因为默认队列大小是50,所以如果你经常测试,你可能会遇到队列问题。如果您还没有更改队列大小..

其他事情,也与队列大小有关。你有几个回报和try-caches。如果发生任何事情,你将无法达到你的联系关闭的程度。因此,当队列已满时,您将获得超时,直到当前连接关闭。其他相关问题,资源泄漏。