Java—用于TCP/HTTP通信的最快流?
我正在尝试编写一个JavaHTTP代理隧道程序,我需要专家提供关于通信使用的最佳和最快流的建议 我已经实现了基本功能,一切正常。唯一的问题是通信速度或性能。我的HTTP代理系统由一个运行在远程服务器上的服务器程序和一个运行在本地计算机上的客户端程序组成。到目前为止,该计划如下所示: Listener.java: ProxyTunnel.java: 服务器程序使用类似的方式,将HTTP请求发送到目标服务器(例如www.stackoverflow.com),并将响应转发给客户端程序,客户端程序将响应转发给本地浏览器Java—用于TCP/HTTP通信的最快流?,java,performance,http,proxy,network-programming,Java,Performance,Http,Proxy,Network Programming,我正在尝试编写一个JavaHTTP代理隧道程序,我需要专家提供关于通信使用的最佳和最快流的建议 我已经实现了基本功能,一切正常。唯一的问题是通信速度或性能。我的HTTP代理系统由一个运行在远程服务器上的服务器程序和一个运行在本地计算机上的客户端程序组成。到目前为止,该计划如下所示: Listener.java: ProxyTunnel.java: 服务器程序使用类似的方式,将HTTP请求发送到目标服务器(例如www.stackoverflow.com),并将响应转发给客户端程序,客户端程序将
bufferedInputsRAM
和BufferedOutputStream
之类的缓冲流是否提高了通信性能java.nio
通道和缓冲区,而不是java.net
Sockets和java.io
Stream,我会获得性能改进吗StringBuilder
/String
来缓冲请求
这是有缺陷的,原因有几个:
- 假设您的HTTP调用仅为文本(ASCII),二进制数据在转换为
并返回到字符串
后将出现格式错误,请参阅:字节[]
- 即使协议是基于文本的,也使用系统的默认编码。我打赌这不是你想要的
- 最后,最重要的部分:不要缓冲整个请求。从传入请求中读取数据块,并在一次迭代中将其立即转发到目标服务器。绝对不需要额外的内存开销和延迟。在收到几个字节后,立即发送它们并忘记它们
请检查,它们包括HTTP客户机/服务器代码。有一点学习曲线,但你可以预期绩效增长几个数量级。愚蠢的问题:你为什么要重新发明轮子?@Michael-O:当然是为了学习和教育目的!侮辱别人之前最好三思而后行!很好的观点。我肯定会在我的节目中考虑这些。但是你没有回答我的其他问题。我的意思是最后的第二和第三个问题。@SeyedMohammad:对。对于#2:一般来说,是的,只要您不缓冲已经缓冲的流。但在您已经以块的形式读取数据的情况下,缓冲只会稍微增加内存消耗,并可能使代码变慢。顺便说一下-非常有用!广告#3-内蒂是建立在NIO之上的,我想我很清楚这是正确的选择。裸NIO通道通常会更快,但您必须正确使用它们。
/**
* Listens and accepts connection requests from the browser
*/
ServerSocket listener = null;
try {
listener = new ServerSocket(port, 128);
} catch (IOException ex) {
ex.printStackTrace(System.err);
}
ExecutorService executor = Executors.newCachedThreadPool();
Socket connection;
while (!shutdown) {
try {
connection = listener.accept();
executor.execute(new ProxyTunnel(connection));
} catch (IOException ex) {
ex.printStackTrace(System.err);
}
}
try {
byte[] buffer = new byte[8192]; // 8-KB buffer
InputStream browserInput = browser.getInputStream();
OutputStream browserOutput = browser.getOutputStream();
// Reading browser request ...
StringBuilder request = new StringBuilder(2048);
do {
int read = browserInput.read(buffer);
logger.log(read + " bytes read from browser.");
if (read > 0) {
request.append(new String(buffer, 0, read));
}
} while (browserInput.available() > 0 && read > 0);
// Connecting to proxy server ...
Socket server = new Socket(SERVER_IP, SERVER_PORT);
server.setSoTimeout(5000); // Setting 5 sec read timeout
OutputStream serverOutput = server.getOutputStream();
InputStream serverInput = server.getInputStream();
// Sending request to server ...
serverOutput.write(request.toString().getBytes());
serverOutput.flush();
// Waiting for server response ...
StringBuilder response = new StringBuilder(16384);
do {
try {
read = serverInput.read(buffer);
} catch (SocketTimeoutException ex) {
break; // Timeout!
}
if (read > 0) {
// Send response to browser.");
response.append(new String(buffer, 0, read));
browserOutput.write(buffer, 0, read);
browserOutput.flush();
}
} while (read > 0);
// Closing connections ...
server.close();
} catch (IOException ex) {
ex.printStackTrace(System.err);
} finally {
try {
browser.close();
} catch (IOException ex) {
ex.printStackTrace(System.err);
}
}
byte[] buffer = new byte[8192]; // 8-KB buffer
//...
browserInput.read(buffer);
//...
request.append(new String(buffer, 0, read));
//...
serverOutput.write(request.toString().getBytes());