簡體   English   中英

HTTP代理服務器Java錯誤

[英]HTTP Proxy Server Java error

  • 作為一項任務,我只能使用ServerSocket和Socket類。 同樣,它也應該是單線程的。

我正在用Java實現HTTP代理服務器,首先它從客戶端獲取請求,然后推送到服務器,然后將響應推送回客戶端。

問題

問題是,我已經成功獲取了請求,將其發送到終端服務器並獲得了正確的HTTP響應。 我也可以在控制台中打印出響應 但是,當我將響應發送到clientServer.outputstream時,它卡住了。 Firefox(請求使用HTTP 1.0,未請求保持活動狀態)似乎可以永久加載,並且沒有任何顯示,也沒有從我的程序中收到Firefox的響應。

調試時檢查的內容

每次頁面開始加載(FF請求)時,總會有2個客戶端套接字。 第一個套接字包含空請求 ,第二個套接字包含正確的請求 我期望的是,只有一個來自Firefox的正確HTTP請求。 這是奇怪的行為嗎?

例:

/0:0:0:0:0:0:0:1:65194
[null request]

/0:0:0:0:0:0:0:1:65195
GET http://www.microsoft.com/ HTTP/1.0
Host: www.microsoft.com
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:15.0) Gecko/20100101 Firefox/15.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Proxy-Connection: close
Cookie: viewkey=lightweight; WT_FPC=id=269eb0e7618962f93a81347585923074:lv=1349229942007:ss=1349229580158; WT_NVR_RU=0=technet|msdn:1=:2=; omniID=c736269c_f430_4e9b_a42a_23a0c965c60a; MUID=212A1766CFE761423CD014BDCBE76158&TUID=1; MC1=GUID=08600fba7f5c5f409e67980d8a027593&HASH=ba0f&LV=20129&V=4&LU=1347643534618; A=I&I=AxUFAAAAAADGBwAA8ezRtqBBHjk3++mP1Bwj9w!!&V=4&CS=119EQ5002j10100; msdn=L=en-US

ServerSocket serverSocket;
try {
    serverSocket = new ServerSocket(60000);
    while (true) {
            clientSocket = serverSocket.accept();
            [...]
            // Extract request, and push to end-server
            // Fetch response from end-server to client, using flush() already
            // Close all input, output
            // Close all sockets
} catch {[...]}

歡迎任何幫助,謝謝!

按要求提供完整代碼,我使用PrintWriter,但在此之前使用Byte沒什么區別(不在乎效率)

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

public class Proxy {

    static String separator = System.getProperty("line.separator");

    public static void main(String args[]) {
        //int port = Integer.parseInt(args[0]); 
        start(60000);
    }

    public static void start(int port) {
        ServerSocket serverSocket;
        try {
            serverSocket = new ServerSocket(port);
            Socket clientSocket = null;
            while (true) {
                clientSocket = serverSocket.accept();

                System.out.println(clientSocket.getRemoteSocketAddress() + "\n" + clientSocket.getLocalSocketAddress() + "\n" + clientSocket.getInetAddress());

                BufferedReader inStreamFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

                String inLine;
                Vector<String> clientRequestHeader = new Vector<String>();
                String rawRequest = "";

                while ((inLine = inStreamFromClient.readLine()) != null) {
                    if (!inLine.isEmpty()) {
                        clientRequestHeader.add(inLine);
                        rawRequest = rawRequest.concat(inLine + separator);
                    } else break;
                }

                while ((inLine = inStreamFromClient.readLine()) != null) 
                    rawRequest = rawRequest.concat(inLine + separator);

                System.out.println(rawRequest);

                if (!rawRequest.isEmpty()) {
                    handleRequest(clientSocket, clientRequestHeader, rawRequest);
                } else {
                    //clientSocket.close();
                                    // Not sure how to handle null request
                }

            }
        } catch (Exception e) {e.printStackTrace();}

    }

    public static void handleRequest(Socket clientSocket, Vector<String> clientRequestHeader, String rawRequest) {
        HTTPRequest request = new HTTPRequest(clientRequestHeader, rawRequest);
        try {
            //System.out.println(rawRequest);

            // Send request to end-server
            Socket endServerSocket = new Socket(request.getHost(), 80);

            PrintWriter outStreamToEndServer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(endServerSocket.getOutputStream())));
            BufferedReader stringReader = new BufferedReader(new StringReader(rawRequest));
            String inLine;
            while ((inLine = stringReader.readLine())!= null) {
                outStreamToEndServer.println(inLine);
            }
            outStreamToEndServer.println();
            outStreamToEndServer.flush();


            // Read response header from end-server
            String responseHeader = "";
            BufferedReader inStreamFromEndServer = new BufferedReader(new InputStreamReader(endServerSocket.getInputStream())); 
            while (!(inLine = inStreamFromEndServer.readLine()).isEmpty()) {
                responseHeader = responseHeader.concat(inLine + separator);
            }

            // Send response header to client
            PrintWriter outStreamToClient = new PrintWriter(new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream())));
            outStreamToClient.println(responseHeader);
            outStreamToClient.flush();

            // Send response body to client
            String responseBody = "";
            while ((inLine = inStreamFromEndServer.readLine()) != null) {
                responseBody = responseBody.concat(inLine + separator);
            }
            outStreamToClient.println(responseBody);
            outStreamToClient.flush();

            endServerSocket.shutdownInput();
            clientSocket.shutdownOutput();
            clientSocket.close();
            endServerSocket.close();

            //endServerSocket = null;
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }

}

首先,您不應該使用PrintWriter傳輸數據,因為HTTP協議不是純文本協議,主體可以包含一些原始數據,例如圖像。

將您的響應轉移代碼替換為以下代碼。

InputStream in = endServerSocket.getInputStream();
OutputStream out = clientSocket.getOutputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1)
{
    out.write(buffer, 0, bytesRead);
}

in.close();
out.close();

第二點,您總是添加換行符

 static String separator = System.getProperty("line.separator");

這是系統特定的行分隔符。 HTTP為HTTP標頭以及HTTP標頭和正文分隔定義了ctrl換行符,因此請更改此設置。

 static String separator = "\r\n";

通過此更改,您將獲得對瀏覽器的響應。

最后一點,您還應該更改客戶端請求的讀取代碼,因為如果要POST某些數據,它將永遠無法工作。 有時,通過示例文件上傳,這些數據將作為原始數據傳輸。

祝好運

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM