Java 当从套接字读取时,如何检测客户端何时完成发送请求?

Java 当从套接字读取时,如何检测客户端何时完成发送请求?,java,sockets,httprequest,httpserver,Java,Sockets,Httprequest,Httpserver,我现在正在编写http服务器,从套接字读取时遇到问题。 我的问题是,来自客户端的inputStream永远不会结束,它会一直读取,直到客户端关闭。 我知道客户端在发送http请求后不会立即关闭与服务器的连接。 当客户端发送了所有请求数据(即标题+正文)时,如何退出while循环 while (in.hasNextLine()) { String line = in.nextLine(); if (line.equals("")){ // last line of request

我现在正在编写http服务器,从套接字读取时遇到问题。 我的问题是,来自客户端的
inputStream
永远不会结束,它会一直读取,直到客户端关闭。 我知道客户端在发送http请求后不会立即关闭与服务器的连接。 当客户端发送了所有请求数据(即标题+正文)时,如何退出
while循环

while (in.hasNextLine()) {
    String line = in.nextLine();

    if (line.equals("")){ // last line of request header is blank
        break; // quit while loop when last line of header is reached
    } else {
        request = request + line + "\n";
    }
}
在阅读了你们的评论和回答之后,这就是我想到的

while (in.hasNextLine()) {
    String line = in.nextLine();

    if (line.equals("")){ // last line of request header is blank
        break; // quit while loop when last line of header is reached
    } else {
        request = request + line + "\n";
    }
}
     is = incoming.getInputStream();
            os = incoming.getOutputStream();
            in = new Scanner(is);
            out = new DataOutputStream(os);

            RequestHandler rh = new RequestHandler();
            int length = 0;
            while (in.hasNextLine()) {
                String line = in.nextLine();
                if (line.equals("")) { // last line of request message
                                        // header is a
                                        // blank line
                    break; // quit while loop when last line of header is
                            // reached
                }

                if (line.startsWith("Content-Length: ")) { // get the
                                                            // content-length
                    int index = line.indexOf(':') + 1;
                    String len = line.substring(index).trim();
                    length = Integer.parseInt(len);
                }

                request = request + line + "\n";
            }

             byte[] body = new byte[length];
             int i = 0;
             while (i < length) {
             byte b = in.nextByte();
             body[i] = b;
             i++;
             }
is=incoming.getInputStream();
os=传入的.getOutputStream();
in=新扫描仪(is);
out=新数据输出流(os);
RequestHandler rh=新的RequestHandler();
整数长度=0;
while(在.hasNextLine()中){
String line=in.nextLine();
if(line.equals(“”){//请求消息的最后一行
//标题是一个
//空行
break;//在返回头的最后一行时退出while循环
//达到
}
if(line.startsWith(“Content-Length:”){//获取
//内容长度
int index=line.indexOf(':')+1;
字符串len=line.substring(index.trim();
长度=整数.parseInt(len);
}
请求=请求+行+“\n”;
}
字节[]正文=新字节[长度];
int i=0;
while(i

但是,我仍然不理解字节读取。我可以编写代码直到-1,但在没有EOF且客户端未关闭连接时仍会被卡住。

根据您正在处理的请求,有3种检测流结束的方法:

while (in.hasNextLine()) {
    String line = in.nextLine();

    if (line.equals("")){ // last line of request header is blank
        break; // quit while loop when last line of header is reached
    } else {
        request = request + line + "\n";
    }
}
  • 如果它是一个
    GET
    HEAD
    请求,您只需要读取HTTP头,请求体通常会被忽略(如果它存在),因此当您遇到
    \r\n\r\n
    时,您会到达请求的末尾(实际上是请求头)
  • 如果是
    POST
    方法,请读取标题中的
    Content Length
    ,并最多读取
    Content Length
    字节
  • 如果是
    POST
    方法,并且
    内容长度
    标题不存在(这很可能发生),则读取直到返回
    -1
    ,这是
    EOF
    的信号
  • 我知道了:)谢谢你们的评论和回答

    while (in.hasNextLine()) {
        String line = in.nextLine();
    
        if (line.equals("")){ // last line of request header is blank
            break; // quit while loop when last line of header is reached
        } else {
            request = request + line + "\n";
        }
    }
    
         is = incoming.getInputStream(); // initiating inputStream
                os = incoming.getOutputStream(); // initiating outputStream
    
                in = new BufferedReader(new InputStreamReader(is)); // initiating
                                                                    // bufferReader
                out = new DataOutputStream(os); // initiating DataOutputSteream
    
                RequestHandler rh = new RequestHandler(); // create a
                                                            // requestHandler
                                                            // object
    
                String line;
                while ((line = in.readLine()) != null) {
                    if (line.equals("")) { // last line of request message
                                            // header is a
                                            // blank line (\r\n\r\n)
                        break; // quit while loop when last line of header is
                                // reached
                    }
    
                    // checking line if it has information about Content-Length
                    // weather it has message body or not
                    if (line.startsWith("Content-Length: ")) { // get the
                                                                // content-length
                        int index = line.indexOf(':') + 1;
                        String len = line.substring(index).trim();
                        length = Integer.parseInt(len);
                    }
    
                    request.append(line + "\n"); // append the request
                } // end of while to read headers
    
                // if there is Message body, go in to this loop
                if (length > 0) {
                    int read;
                    while ((read = in.read()) != -1) {
                        body.append((char) read);
                        if (body.length() == length)
                            break;
                    }
                }
    
                request.append(body); // adding the body to request
    

    我想与大家分享我的代码:

    while (in.hasNextLine()) {
        String line = in.nextLine();
    
        if (line.equals("")){ // last line of request header is blank
            break; // quit while loop when last line of header is reached
        } else {
            request = request + line + "\n";
        }
    }
    
    private static String getClientRequest(Socket client) throws IOException, SocketException {
        System.out.println("Debug: got new client " + client.toString());
        BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8"));
    
        StringBuilder requestBuilder = new StringBuilder();
        String line;
        int contectLegnth = 0;
        
        while (!(line = br.readLine()).isBlank()) {
            requestBuilder.append(line + "\r\n");
            if (line.toLowerCase().startsWith("content-length")) {
                contectLegnth = Integer.parseInt(line.split(":")[1].trim());
            }
        }
        
    
        StringBuilder requestBodyBuilder = new StringBuilder();
        if (contectLegnth > 0) {
            int read;
            while ((read = br.read()) != -1) {
                requestBodyBuilder.append((char) read);
                if (requestBodyBuilder.length() == contectLegnth)
                    break;
            }
            requestBuilder.append("\r\n" + requestBodyBuilder);
        }
       
        return requestBuilder.toString();
    }
    

    如果它是
    GET
    ,则可以在获取
    \r\n\r\n
    后停止,如果它有请求正文,则可以在从请求正文读取
    内容长度
    字节后停止。Scanner.nextByte()根据当前基数进行解析;它不返回原始字节。您应该为此使用
    DataInputStream
    。是的,我知道它的
    readLine()
    方法已被弃用。对于所有方法,包括GET、HEAD、PUT、POST、DELETE等,省略(1)并仅使用(2)和(3)。。。如果客户端正在执行keepalive,则您必须读取所有请求的末尾,否则您将无法正确获取下一个请求。您好,@EJP,感谢您提及
    keepalive
    。如果
    内容长度
    不存在,如果客户端正在执行
    保留活动
    ,如何检测请求的结束?这不是法律情况。如你在(3)中所述,如果客户需要保持活动状态,他必须发送一个内容长度。大多数非
    GET
    /
    HEAD
    请求可以有一个消息正文,因此将#2和#3限制为
    POST
    是错误的。此外,“如果客户端正在执行保持活动状态,则必须发送内容长度”也不是真的。如果改为使用
    传输编码:分块
    内容类型:多部分/..
    ,则
    内容长度
    是可选的。而读取直到
    EOF
    对请求无效,仅对响应有效。请参阅,以了解在所有场景中检测消息结束时需要遵循的确切规则,无论是否使用keep alive。