我的编程任务要求我在客户端和服务器之间创建一个代理。我的客户端通过代理向服务器发出请求,然后代理将其转发并将服务器的响应返回给客户端。
以下是我采取的步骤:
1) 从客户端获取请求并将请求数据存储到字节数组中
2) 使用缓冲读取器读取字节数组
3) 从host:header字段获取主机名,并使用它创建一个serverSocket
4) 将请求数据转发到serverSocket outputstream
5)从serverSocket输入流中检索响应数据到另一个字节数组中
6)将字节数组中的内容写入clientSocket输出流
但是,在步骤6之后,浏览器无法显示响应数据。有什么帮助吗?
import java.io.*;
import java.net.*;
import java.util.*;
public class proxy2 {
public static void main(String args[]) throws Exception
{
int port = Integer.parseInt(args[0]);
File fileSub= new File(args[1]); //fileSub
File fileRediect = new File(args[2]); //fileRedirect
ServerSocket listener = new ServerSocket(port);
while (true) {
proxy_func(listener.accept());
}
}
public static void proxy_func(Socket clientSocket) throws Exception{
OutputStream outputToClient = clientSocket.getOutputStream();
//store clientSocket's inputstream into a buffer
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead; //start offset in the data
byte[] data = new byte[16384]; //create byte array
//read each byte from InputStream and write it to a ByteArrayOutputStream
while((nRead = clientSocket.getInputStream().read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush(); //forces any buffered bytes to be written out
data = buffer.toByteArray(); //retrieve the underlying byte array
System.out.println(new String(data));
//create buffer reader for clientSocket's inputstream
InputStream inputStream = new ByteArrayInputStream(data);
BufferedReader readFromClient = new BufferedReader(new InputStreamReader(inputStream));
String[] strArr;
String line;
String hostname = null;
//get hostname
while( (line=readFromClient.readLine()) != null)
{
strArr = line.split(" ");
if(strArr[0].equals("Host:"))
hostname = strArr[1];
}
System.out.println("Host: " + hostname);
//create server socket
Socket serverSocket = new Socket(hostname, 80);
OutputStream outputToServer = serverSocket.getOutputStream();
InputStream inputFromServer = serverSocket.getInputStream();
//forward request to server
System.out.println("forward request to server...");
outputToServer.write(data);
//receive data from server and write response back to client
byte[] receivedData = new byte[16384];
int size;
while((size = inputFromServer.read(receivedData)) != -1)
{
System.out.println("write response back to client...");
System.out.println("size: " + size);
System.out.println(new String(receivedData));
outputToClient.write(receivedData, 0, size);
}
System.out.println("flushing...");
outputToClient.flush();
outputToClient.close();
}
}
因此,我基本上遵循以下I/O布局:
{
OutputStream outputToClient = clientSocket.getOutputStream();
BufferedReader readFromClient = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
//step 1
//get the HTTP request header from your firefox
String line = readFromClient.readLine();
//if the Content_Length within the HTTP header exists and not equals to 0
char [] buffer = new char [#];
readFromClient.read(buffer, 0, Content_Length); //get the body message
OutputStream outputToServer = serverSocket.getOutputStream();
InputStream inputFromServer = serverSocket.getInputStream();
//step 2
outputToServer.write(Bytes[]) //forword the HTTP requests to server host.
//step 3
byte[] data = new byte[#];
while ((size = inputFromServer.read(data)) != -1) //get the response data from server
{
//step 4
outputToClient.write(data, 0, size); //forward the data to your firefox
}
}
你这样做完全错了。HTTP代理只需读取CONNECT命令并执行它。之后,您只需尽可能快地同时在两个方向复制字节。您越是试图了解代理中的HTTP协议,您将引入的错误就越多。
好的,我找到了问题的原因。我的while循环被阻止,因为我没有检测到HTTP请求的结束。这个答案简洁地解决了我的问题:https://stackoverflow.com/a/9542710
这里是为那些偶然发现这个问题并迷路的人发布的。
以下是我的更新代码,可以使用(注意,我添加了一个方法来检测HTTP请求的结束):
import java.io.*;
import java.net.*;
import java.util.*;
public class proxy2 {
public static void main(String args[]) throws Exception
{
int port = Integer.parseInt(args[0]);
File fileSub= new File(args[1]); //fileSub
File fileRediect = new File(args[2]); //fileRedirect
//create listener socket to listen for requests from browser
ServerSocket listener = new ServerSocket(port);
while (true) {
proxy_func(listener.accept());
}
}
public static void proxy_func(Socket clientSocket) throws Exception{
OutputStream outputToClient = clientSocket.getOutputStream();
InputStream inputFromClient = clientSocket.getInputStream();
//store clientSocket's inputstream into a buffer
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead; //start offset in the data
byte[] data = new byte[16384];
//read each byte from InputStream and write it to a ByteArrayOutputStream
while((nRead = inputFromClient.read(data, 0, data.length)) != -1) {
System.out.println("reading from client...");
buffer.write(data, 0, nRead);
//if reached end of HTTP request, break out of this loop
if(endOfRequest(data) == true)
break;
}
buffer.flush(); //forces any buffered bytes to be written out
data = buffer.toByteArray(); //retrieve the underlying byte array
System.out.println(new String(data));
//create buffered reader for byte array input stream (request data)
InputStream inputStream = new ByteArrayInputStream(data);
BufferedReader readFromClient = new BufferedReader(new InputStreamReader(inputStream));
String[] strArr;
String line;
String hostname = null;
//get hostname
while( (line=readFromClient.readLine()) != null)
{
strArr = line.split(" ");
if(strArr[0].equals("Host:"))
hostname = strArr[1];
}
System.out.println("Host: " + hostname);
//create server socket
Socket serverSocket = new Socket(hostname, 80);
OutputStream outputToServer = serverSocket.getOutputStream();
//InputStream inputFromServer = serverSocket.getInputStream();
//forward request to server
System.out.println("forward request to server...");
outputToServer.write(data);
//receive data from server and write response back to client
DataInputStream inputFromServer = new DataInputStream(serverSocket.getInputStream());
byte[] receivedData = new byte[1024];
int size;
while((size = inputFromServer.read(receivedData, 0, receivedData.length)) != -1)
{
System.out.println("write response back to client...");
System.out.println(new String(receivedData));
outputToClient.write(receivedData, 0, size);
outputToClient.flush();
}
System.out.println("done sending");
outputToClient.close();
}
//method to detect end of HTTP request
//return true if detected, otherwise false
public static boolean endOfRequest(byte[] data) throws Exception
{
System.out.println("parsing request..");
BufferedReader br = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(data)));
String line;
while( (line=br.readLine()) != null) {
if (line.equals(""))
return true;
}
return false;
}
}
最后一部分有一个问题:
byte[] receivedData = new byte[16384];
int size;
while((size = inputFromServer.read(receivedData)) != -1)
{
System.out.println("write response back to client...");
System.out.println("size: " + size);
System.out.println(new String(receivedData));
}
outputToClient.write(receivedData);
那么,假设服务器发回100万字节。循环按16384字节的块读取它们,一旦读取了所有的块,它将在上次读取后将剩余的内容发回到receivedData缓冲区。因此,浏览器将只接收服务器发送的1000000字节中的16384字节。
您必须将从服务器读取的所有内容发送到浏览器:
byte[] receivedData = new byte[16384];
int size;
while((size = inputFromServer.read(receivedData)) != -1)
{
System.out.println("write response back to client...");
System.out.println("size: " + size);
System.out.println(new String(receivedData));
outputToClient.write(receivedData, 0, size);
}
我添加了这个依赖项: 这是我的: 我的如下所示: 我在另一个线程中读到,我必须将更改为,但这并没有改变任何东西:
问题内容: 对于某些集成项目,我想从非Java客户端查询JMX代理。 到目前为止,我发现了两个选项,ws-jmx- connector(基于Soap)和mx4j及其返回XML文档响应的JMX HTTP适配器 。基于JSR 262的ws-jmx- connector似乎不再处于积极开发中。我没有尝试过MX4J,所以我不知道是否可以在J2SE中将HTTP适配器与标准JMX实现一起使用。 是否还有其他软
我正在尝试基于Apache示例和FTPSClient类,使用Apache Commons网络库开发Java FTPS客户端。要运行de代码,我使用Java8,更新45。 当我调用“retrieveFile”方法时,会发生异常。我不确定,但我相信用于传输文件的连接没有使用上面指定的HTTP代理。 使用FileZilla客户端,我可以使用相同的配置传输文件。 我如何解决这个问题? 我的代码: 输出:
是否可以在Silverlight中创建代理客户端,这意味着Silverlight应用程序知道代理服务器的主机、端口、用户名和密码,然后建立与代理服务器的连接? 然后,Silverlight应用程序将能够向该代理服务器后面的资源发出HTTP请求。 这样,Silverlight应用程序就可以访问某些资源,而无需首先在客户端计算机上安装第三方代理客户端,因为代理客户端将是Silverlight应用程序本
我正在做一个项目,其中有一个Java调度器,它是一个HTTP客户端,并将xml作为数据发送到我的节点应用程序。在application.js的索引函数中,我编写了接收xml并将相应的xml转换为json的逻辑,但当我运行app时,我会从acs获得404响应代码,但当我从浏览器发送请求时,这也是一样的。请建议我在这方面缺少什么。我正在张贴Java http客户端和节点acs代码。 Java HTTP
使用iText 5.5.11从maven回购https://mvnrepository.com/artifact/com.itextpdf/itextpdf/5.5.11 基本多语言平面中的非代理字符在生成的pdf上呈现,但代理字符不呈现。 编辑:也尝试使用编码为“UniGB-UCS2-H”的字体“STSong Light”(如本书中的示例)。结果相同-缺少代理字符。 Edit2:让它与"SimS