我的http通讯遇到了奇怪的问题。我写了非常简单的http服务器和客户端。
Http服务器:
public class SimpleHttpServer {
public void run() throws IOException {
final ServerSocket serverSocket = new ServerSocket(8080);
while(true)
{
final Socket connectionSocket = serverSocket.accept();
new Thread(new Runnable() {
@Override
public void run() {
try {
try(BufferedReader in = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
DataOutputStream out = new DataOutputStream(connectionSocket.getOutputStream())){
System.out.println(in.readLine());
String line = null;
while((line = in.readLine()) != null && !line.trim().isEmpty()){
System.out.println(line);
}
byte[] message = loadFile(); //load some gzipped jpg image from disk
out.write(ascii("HTTP/1.1 200 OK\n"));
out.write(ascii("Content-Type: image/jpg\n"));
out.write(ascii(String.format("Content-Length: %s\n", message.length)));
out.write(ascii("content-encoding: gzip\n"));
out.write(ascii("\n"));
out.write(message);
}
}catch(Exception e){
e.printStackTrace();
}
}
}).start();
}
}
}
Http客户端:
public class SimpleHttpClient {
public void run() throws IOException {
String host = "localhost";
int port = 8080;
Socket socket = new Socket(host, port);
try (OutputStream out = socket.getOutputStream()) {
out.write(ascii("GET / HTTP/1.1\n"));
out.write(ascii("User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36\n"));
out.write(ascii("Accept-Encoding: gzip, deflate, sdch\n"));
out.write(ascii("Accept-Language: pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4\n"));
out.write(ascii("\n"));
try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
String line = null;
while ((line = in.readLine()) != null && !line.trim().isEmpty()) {
System.out.println(line);
}
}
}
}
}
所以,当我删除带有用户代理标题的行时,我会得到我期望的结果:
HTTP/1.1 200 OK
Content-Type: image/jpg
Content-Length: 378632
content-encoding: gzip
这很清楚也很明显。
但是当这个标题出现时,答案是不同的:
HTTP/1.1 200 OK
Content-Type: image/jpg
Transfer-Encoding: chunked
我在服务器端没有改变任何东西。在每个请求中,我发送相同的响应。用户代理是从chrome浏览器复制的。
两个实现都是普通的java套接字,而不是第三方libriares。 所以我的问题是:它是如何发生的?有什么东西被缓存了吗?但在哪里?
请不要查看代码质量。这只是一个例子。我不想在生产中使用它:)
编辑1:
private byte[] ascii(String value) throws UnsupportedEncodingException {
return value.getBytes(StandardCharsets.US_ASCII);
}
编辑2:
我做过一些研究。当用户代理包含" AppleWebKit",协议名称为HTTP且端口为80或8080时,就会发生这种情况。 此外,它发生在Windows 10上(我在两台不同的计算机上查看)。在Linux(Ubuntu 16.04和Debian 8)上,一切都很好。
也许我应该改变问题的标题?但是如何用一个简短的句子来解释这个问题?