1

我在 HTTP 服务器上做一些基准测试。为了避免与 HTTP 库的潜在冲突,我直接使用 Socket 打开连接,没有 HTTP 持久连接。

Java 代码打开并连接一个InputStream连接到加载的 HTTP 服务器的套接字。它在 Linux 上运行。

我看到这两种情况都可能发生:

  • 套接字连接 (new Socket()) 可能需要很长时间。如果服务器在接受新连接方面有积压,这是有道理的。
  • 套接字连接速度很快,但延迟高达 1500 毫秒,在 read() 返回 -1 表示流位于“文件”末尾时是在最后一次读取中。这个我不明白。

代码遵循标准,添加了一些时序代码:

final byte[] buffer = new byte[8192];
int size = inputStream.read(buffer);

while (size > 0) {
    // Copy the buffer
    size = inputStream.read(buffer);
}
4

3 回答 3

5

read在您已经收到服务器将要发送的所有数据之后,您正在调用。这是个错误。一旦您收到完整的回复(由 HTTP 协议确定),您应该停止调用read. 您正在等待连接超时,这很愚蠢。

HTTP 协议会告诉您何时收到完整的回复,而不是 TCP 协议。您期望 TCP 堆栈能够理解 HTTP。它不是。它不知道您何时收到完整的回复。

于 2012-09-03T12:23:32.633 回答
2

套接字连接速度很快,但延迟高达 1500 毫秒,在 read() 返回 -1 表示流位于“文件”末尾时是在最后一次读取中。这个我不明白。

假设情况与您解释的完全一样;即您只是连接到端口 80 并尝试读取数据:

  • 服务器很可能正在等待您的客户端代码发送请求。
  • 服务器在 1.5 秒后超时读取,然后关闭其套接字的两侧。
  • 这会导致客户端套接字看到一个 EOF ... 通过-1read(...)调用返回来向您的代码发出信号。

基本上,如果您希望服务器向您发送响应,您的代码必须向服务器发送格式正确的 HTTP 请求。

另一方面,如果您的代码确实发送了格式正确的 HTTP 请求,那么该行为可能是由于您的代码试图读取服务器必须发送的更多数据......结合发送指定持久连接的请求(参见 HTTP 1.1 规范,第 8.1 节)。

于 2012-09-03T12:31:11.993 回答
1

收到带有 JSON 正文的响应时,我遇到了类似的问题。经过几次实验,我检测到该程序在读取正文时挂起。所以,我解决了这个问题,通过从标题中读取 Content-Length ,在空白行(在 header 和 body 之间)之后停止,然后只读取必要的字符。这是代码:

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

public class TelegramSocketClient {
    private final String CONTENT_LEN = "Content-Length:";
    Socket clientSocket;
    SSLSocket sslSocket;
    PrintWriter out;
    BufferedReader in;
    public void startSSLConnection(String ip, int port) throws IOException {
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory
                .getDefault();
        sslSocket = (SSLSocket) factory.createSocket(ip, port);

        out = new PrintWriter(sslSocket.getOutputStream(), true);
        in = new BufferedReader(
                new InputStreamReader(sslSocket.getInputStream(), StandardCharsets.UTF_8));
    }

    public String sendMessage(String msg) throws IOException {
        out.println(msg);
        String line = null;
        int contentLen = 0;
        while ((line = in.readLine()) != null && !line.isEmpty()) {
            System.out.println(line);
            if(line.startsWith(CONTENT_LEN)) {
                contentLen = Integer.parseInt(line.substring(CONTENT_LEN.length() +1, line.length()));
            }
        }

        char [] buff = new char[contentLen];
        in.read(buff, 0, buff.length);
        return new String(buff, 0, buff.length);
    }

    public void stopConnection() throws IOException {
        in.close();
        out.close();
        clientSocket.close();
    }
}
于 2020-03-17T20:31:04.153 回答