【问题标题】:Java, HTTP, & Sockets: When to stop reading the request but keep the socket open?Java、HTTP 和套接字:何时停止读取请求但保持套接字打开?
【发布时间】:2017-04-28 18:35:28
【问题描述】:

我的团队正在使用 Java 从头开始​​构建一个基本的 HTTP 服务器,但是一旦我们的读取器线程用完请求文本以从套接字的输入流中读取,它们就会阻塞。 与questions asked previously 不匹配的我们情况的一些独特点:

  • 我们希望在处理请求并产生响应以发回时保持套接字打开
  • 我们一开始并不解析数据,而是首先从套接字中读取数据,然后将整个数据放入一个恢复文件中。然后我们开始从文件中解析和验证,以确保在发生灾难时我们不会丢失请求。

基本代码:

public void readSocket() {
    receivedTime = System.currentTimeMillis();
    requestFile = new File("recovery/" + receivedTime + ".txt");
    try(
        FileWriter fw = new FileWriter(requestFile);
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        BufferedWriter out = new BufferedWriter(fw); 
    )
    {
        String line;
        while((line = in.readLine()) != null){ //TODO: this is where it blocks after reading past the last line of the request. 
            out.write(line);

        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

【问题讨论】:

  • 为什么不使用 Java 自己的 HttpServer 类呢?为什么要缓存容灾请求?如果出现问题,客户端无论如何都会消失,因此您无法发回响应,那么为什么要恢复呢? HTTP 本来就是无状态的。让客户端重新连接并再次发送请求。
  • 项目规范要求我们自己构建。

标签: java sockets http


【解决方案1】:

readLine() 仅在“已到达流的末尾”时返回null,即套接字已被对方关闭。当readLine() 读取没有前面数据的换行符时,它会返回一个非空的String,其length 为0。因此您需要相应地修复while 循环:

public void readSocket() {
    receivedTime = System.currentTimeMillis();
    requestFile = new File("recovery/" + receivedTime + ".txt");
    try(
        FileWriter fw = new FileWriter(requestFile);
        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        BufferedWriter out = new BufferedWriter(fw); 
    )
    {
        String line;

        // read request headers...
        do {
            line = in.readLine();

            if (line == null) return; // socket closed

            out.write(line);
            out.NewLine();
            out.flush();

            if (line.isEmpty()) break; // end of headers reached

            // process line as needed...
        }
        while (true);

        // check received headers for presence of a message
        // body, and read it if needed. Refer to RFC 2616
        // Section 4.4 for details...

        // process request as needed...

    } catch (IOException e) {
        e.printStackTrace();
    }
}

另见:

While reading from socket how to detect when the client is done sending the request?

【讨论】:

  • 其实确实是这样,但是对于有payload的请求就不行了。看起来,我必须立即解析出 HTTPMethod 并确定它是否应该在空行上中断或等到有效负载之后,这也需要解析出 content-length 标头。
  • @MDjava 在我的示例中都属于“检查收到的标头是否存在消息正文,并在需要时阅读它”占位符。
猜你喜欢
  • 2012-11-23
  • 2013-04-19
  • 2017-09-30
  • 1970-01-01
  • 2017-09-28
  • 1970-01-01
  • 1970-01-01
  • 2013-02-13
  • 2017-02-10
相关资源
最近更新 更多