2010-11-27 32 views
2

我試圖讓一個簡單的多線程代理工作在Java中。然而,我沒有設法讓網頁在我的瀏覽器中顯示出來,在第一次GET請求和網頁的響應之後,程序就被卡住了(正如你從我的代碼中看到的那樣,我正在打印所有的東西調試的標準輸出,在那裏我看到了網頁的源代碼,但是在打印出「After Client Write」之後,沒有任何事情發生(沒有例外,沒有任何事情......))。簡單的Java HTTP代理與套接字卡住沒有錯誤消息

import java.net.*; 
import java.util.*; 

import java.io.*; 

public class Proxy 
{ 

public static void main(String[] args) 
{ 
    try 
    { 
     ServerSocket listensocket = new ServerSocket(Integer.valueOf(args[0])); 
     while(true) 
     { 
      System.out.println("wait"); 
      Socket acceptsocket = listensocket.accept(); // blocking call until it receives a connection 
      myThread thr = new myThread(acceptsocket); 
      thr.start(); 
     } 

    } 
    catch(IOException e) 
    { 
     System.err.println(">>>>" + e.getMessage()); 
     e.printStackTrace(); 
    } 

} 

static class myThread extends Thread 
{ 
    Socket acceptsocket; 
    int host, port; 

    String url; 

    myThread(Socket acceptsocket) 
    { 
     this.acceptsocket=acceptsocket; 
    } 
    public void run() { 
     try 
     { 
      System.out.println("hello"); 

      Socket client = acceptsocket; 
      //client.setSoTimeout(100); 
      InputStream clientIn = client.getInputStream(); 
      //BufferedInputStream clientIn=new BufferedInputStream(clientis); 
      OutputStream clientOut = client.getOutputStream(); 
      System.out.println("hello"); 

      String clientRequest = readStuffFromClient(clientIn); // parses the host and what else you need 
      System.out.print("Client request: -----\n"+clientRequest); 

      Socket server; 
      server = new Socket("xxxxxxxxxxxxx" , 80); 


      InputStream serverIn = server.getInputStream(); 
      //BufferedInputStream serverIn=new BufferedInputStream(serveris); 
      OutputStream serverOut = server.getOutputStream(); 


      serverOut.write(clientRequest.getBytes()); 
      serverOut.flush(); 

      String serverResponse = readStuffFromClient(serverIn); 

      System.out.print("Server Response: -----\n"+serverResponse); 

      clientOut.write(serverResponse.getBytes()); 
      clientOut.flush(); 
      System.out.println("After Client Write"); 

      clientIn.close(); 
      clientOut.close(); 
      serverIn.close(); 
      serverOut.close(); 
      server.close(); 
      client.close(); 


     } 
     catch(Exception e) 
     { 
      System.out.println(e); 
     } 
    } 
    private String readStuffFromClient(InputStream clientdata) 
    { 
     ByteArrayOutputStream response = new ByteArrayOutputStream(); 
     StringBuffer request=new StringBuffer(8192); 
     int i, httpstart,n=-1 ; 
     byte[] buffer = new byte[8192]; 

     System.out.println("beforetry"); 

     try 
     { 

      while((n = clientdata.read(buffer))!=-1) 
      { 
      System.out.println("before"); 
      response.write(buffer,0,n); 
      //response.flush(); 
       } 
       request=new StringBuffer(response.toString()); 
       /*System.out.println("new:"+n+" "+ request.toString()); 
       System.out.println("End client data");*/ 

     }  
     catch (Exception e) 
     { 
      System.out.println("here"); 
      System.out.println(e); 
      e.printStackTrace(); 
      i = -1; 
     } 




      System.out.println("End manipulation method"); 
      return request.toString(); 
     } 
} 



} 

(這是我的程序的精簡不靈例如,從註釋中可以看到我已經嘗試過使用的BufferedInputStream)。一般來說,即使對於來自瀏覽器的第一個GET請求,該程序也是非常沒有響應的。當我只讀取一次clientdata(不是循環)時,我會進一步,例如獲得更多的GET/Response對,但在某些時候,程序仍然卡住。

不知何故,我認爲無論我有一個真正的微不足道的錯誤,我只是無法看到,或程序應該工作,但根本沒有真正的原因。

任何幫助表示讚賞,在此先感謝!

回答

-1

嘗試先獲取OutputStream然後再獲取InputStream!

InputStream clientIn = client.getInputStream(); 
OutputStream clientOut = client.getOutputStream(); 

將其更改爲:

OutputStream clientOut = client.getOutputStream(); 
InputStream clientIn = client.getInputStream(); 
+0

謝謝!我試過了,但沒有幫助,程序仍然表現相同 – Mark 2010-11-27 09:30:13

+0

呃,實際上發生的情況是讀取的mehod會阻塞你的線程,因爲它不知道是否有更多的數據需要讀取。 – capsula 2010-11-27 11:25:06

-1

這將使其工作:

它會檢查是否有可用來讀取

還有更多的數據,則需要使用很重要BufferedIS因爲我認爲ByteArrayIS沒有實現可用的方法。

BufferedInputStream bis = new BufferedInputStream(clientdata); 
      System.out.println("beforetry"); 

      try { 
       while(bis.available() > 0){ 
        n = bis.read(buffer); 
        response.write(buffer, 0, n); 
       } 
0

需要兩個線程:一個從客戶端讀取和寫入服務器,一個做相反的,對於每一個接受的套接字。還有一個更爲微妙的地方:當你從一個方向讀取EOS時,關閉對方的輸出插口,然後如果該線程的輸入插口已經關閉輸出,關閉兩個插口。在這兩種情況下退出讀取EOS的線程。