服务器仅从请求中读取标头时,Http客户端未收到任何响应 [英] Http client receives no response when server reads only headers from request

查看:48
本文介绍了服务器仅从请求中读取标头时,Http客户端未收到任何响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在弄乱Java中的HTTP和套接字,希望您能对此有所了解:

I'm messing around with HTTP and sockets in Java and was hoping you could shed some light on this:

当我用Java SE 11编写的HTTP服务器未读取整个请求然后进行响应时,客户端无法获取该请求或发生错误.这是为什么?在服务器读取整个请求之前,客户端是否无法读取响应?如果在以下代码段中执行了对readBody的调用,则可以正常工作.如果响应具有Content-Length标头和文本正文,它也可以正常工作.这实际上让我感到困惑.

When my HTTP server written in Java SE 11 does not read the entire request and then responds, the client does not get it or gets an error. Why is that? Is the client unable to read the response before the server has read the entire request? If the call to readBody is executed in the snippet below, this works fine. It also works fine if the response has the Content-Length header and a text body. That is actually more puzzling to me.

我的示例请求是带有数据 fds 的POST.邮递员说无法获得任何请求",而curl说卷曲:(56)接收失败:对等方重置连接".

My example request is a POST with the data fds. Postman says "Could not get any request" and curl says "curl: (56) Recv failure: Connection reset by peer".

import java.io.*;
import java.net.Socket;
import java.util.*;

class Handler {

    public synchronized void read(Socket incoming) {
        try (incoming;
             OutputStream outputStream = incoming.getOutputStream();
             InputStream inputStream = incoming.getInputStream();
             PrintWriter pw = new PrintWriter(outputStream)) {

            writeRequest(inputStream);
            pw.print("HTTP/1.1 200 OK\r\n");
            pw.print("\r\n");
            pw.flush();
        } catch (IOException e) {
            System.out.println("ERROR: " + e.getMessage());
            e.printStackTrace();
        }
    }

    private void writeRequest(InputStream inputStream) throws IOException {
        String verbLine = readLine(inputStream);

        Map<String, String> headers = readHeaders(inputStream);

        //readBody(inputStream, headers);
    }

    private void readBody(InputStream inputStream, Map<String, String> headers) throws IOException {
        Optional<String> optKey = headers.keySet().stream()
                .filter(k -> k.equalsIgnoreCase("Content-Length"))
                .findFirst();
        if (optKey.isPresent()) {
            int contentLength = Integer.parseInt(headers.get(optKey.get()));
            byte[] bytes = inputStream.readNBytes(contentLength);
        }
    }

    private Map<String, String> readHeaders(InputStream inputStream) throws IOException {
        Map<String, String> headers = new HashMap<>();
        while (true) {
            String line = readLine(inputStream);
            if (line == null || line.isEmpty()) {
                return headers;
            }
            String key = line.split(":")[0].trim();
            String value = line.split(":")[1].trim();
            headers.put(key, value);
        }
    }

    private String readLine(InputStream inputStream) throws IOException {
        byte[] buf = new byte[200];
        int offset = 0;
        while (true) {
            int read = inputStream.read();
            if (read == -1) {
                return null;
            }
            buf[offset] = (byte) read;
            if (buf[0] == '\n' || (buf[0] == '\r' && buf[1] == '\n')) {
                return "";
            }
            if (buf[offset] == 0x0A) {
                int endOfLine = buf[offset - 1] == 0x0D ? offset - 1 : offset;
                return new String(buf, 0, endOfLine);
            } else {
                offset++;
            }
        }
    }
}

推荐答案

如果在仍有未读数据的情况下关闭服务器上的套接字,则会导致客户端连接重置错误.因为您没有阅读完整的请求,所以在这里发生这种情况.如果尚未读取服务器的完整响应,则该错误将向用户显示.

If you close a socket at the server while there are still unread data it will result in a connection reset error at the client. This happens here since you don't read the full request. This error will be exposed to the user if the full response from the server was not read yet.

如果您发送的响应内容为 content-length ,然后是完整的正文,则客户端将读取完整的响应,因此错误将被忽略.相反,如果您既不发送 content-length 也不使用分块编码,则客户端将期望响应以适当的TCP连接结束而结束.在这种情况下,连接重置将传播给用户,因为尚未(正确)读取服务器的完整响应.

If you send the response with a content-length and then the full body then the client will have read the full response and thus the error will be ignored. If instead you send neither content-length nor use chunked encoding the client will expect the response to end with a proper close of the TCP connection. In this case the connection reset will be propagated to the user since the full response from the server was not (properly) read yet.

这篇关于服务器仅从请求中读取标头时,Http客户端未收到任何响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆