我正在使用java創建一個簡單的Web代理應用程序。基本上,主要方法創建一個RequestReceiver對象,該對象具有監聽Web瀏覽器http請求的ServerSocket。一個新的Connection對象是從serverSocket.accept()返回的套接字創建的,並被放入一個線程池中。Java主線程不會喚醒ServerSocket接受
我遇到的問題是,並非所有的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語句
您的服務器套接字看起來像接受單個連接,然後退出。是不斷調用啓動方法的東西? – jtahlborn 2015-01-31 22:18:16
@jtahlborn主類有一個連續調用start()方法的while(true)循環 – Darkphenom 2015-01-31 22:22:04
不要編寫這樣的代碼。每個方法只能有一個catch(IOException)塊。依賴於'try'塊中代碼成功的代碼應該在同一個'try'塊中。並且不要在內部循環中沖洗。 – EJP 2015-01-31 23:32:41