简体   繁体   English

HTTP代理服务器Java错误

[英]HTTP Proxy Server Java error

  • As an assignment, I am allowed to use ServerSocket and Socket class only. 作为一项任务,我只能使用ServerSocket和Socket类。 Also it should be single-threaded as well. 同样,它也应该是单线程的。

I'm implementing a HTTP proxy server in Java, first it fetches request from client and then pushes to server, and then pushes the response back to the client. 我正在用Java实现HTTP代理服务器,首先它从客户端获取请求,然后推送到服务器,然后将响应推送回客户端。

The problem 问题

The problem is, I have successfully get the request, send it to the end-server and get the proper HTTP response. 问题是,我已经成功获取了请求,将其发送到终端服务器并获得了正确的HTTP响应。 I also can do print out the response in console . 我也可以在控制台中打印出响应 But it got stuck when I send the response to clientServer.outputstream. 但是,当我将响应发送到clientServer.outputstream时,它卡住了。 Firefox (requested to use, HTTP 1.0, no keep-alive requested) seems to load forever and nothing shows, and no response Firefox received from my program as well. Firefox(请求使用HTTP 1.0,未请求保持活动状态)似乎可以永久加载,并且没有任何显示,也没有从我的程序中收到Firefox的响应。

What I inspect when debug 调试时检查的内容

Everytime a page start to load (FF request), there are always 2 client sockets. 每次页面开始加载(FF请求)时,总会有2个客户端套接字。 First socket contains null request , and second socket contains proper request . 第一个套接字包含空请求 ,第二个套接字包含正确的请求 What I expect was that only one proper HTTP request from Firefox. 我期望的是,只有一个来自Firefox的正确HTTP请求。 Is that a weird behavior? 这是奇怪的行为吗?

example: 例:

/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

Code

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 {[...]}

Any help is welcomed, thank you! 欢迎任何帮助,谢谢!

Full code as requested, I use PrintWriter, but before that using Byte makes no difference (not care efficiency) 按要求提供完整代码,我使用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();
        } 
    }

}

first you should not use PrintWriter to transfer the Data, because the HTTP protocol isn't a pure text protocol the body can contain some raw data like images. 首先,您不应该使用PrintWriter传输数据,因为HTTP协议不是纯文本协议,主体可以包含一些原始数据,例如图像。

Replace your response transfer code with the code below. 将您的响应转移代码替换为以下代码。

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

Second point, you add always as line break the 第二点,您总是添加换行符

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

This is the System specific line seperator. 这是系统特定的行分隔符。 HTTP defines for the HTTP header and for the http header and body separation the ctrl line break charaters, so change this. HTTP为HTTP标头以及HTTP标头和正文分隔定义了ctrl换行符,因此请更改此设置。

 static String separator = "\r\n";

With this changes you will get your response to your browser. 通过此更改,您将获得对浏览器的响应。

Last Point you should change your client request read code also, because it will not always work if you want POST some data. 最后一点,您还应该更改客户端请求的读取代码,因为如果要POST某些数据,它将永远无法工作。 Sometimes this data will transfered as raw data, by example file uploads. 有时,通过示例文件上传,这些数据将作为原始数据传输。

Good Luck 祝好运

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM