BufferedReader.ready()行为的差异

时间:2017-07-16 06:36:31

标签: java sockets inputstream java-io

我正在尝试使用套接字模拟简单的HTTP服务器和客户端。 BufferedReader用于逐行读取请求。 为了识别套接字输入流的结束,使用BufferedReader的ready()方法。

Java Doc for ready:

Returns:
     True if the next read() is guaranteed not to block for 
      input, false otherwise. Note that returning false does not 
      guarantee that the next read will block.

当我从浏览器访问服务器时,此工作正常。但是当我从java应用程序中尝试它时,继续返回true。我是否需要在Java程序中包含任何内容,以便BufferedReader准备好返回false?

服务器:

package com.test.http.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class HttpWebServer {

    private static final String ROOT_URL = "/";
    private static final String FAV_ICON_URL = "/favicon.ico";
    private static final String GET_METHOD = "GET";
    private static final String POST_METHOD = "POST";

    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8081);

        System.out.println("Established connection........."
                + serverSocket.getLocalSocketAddress());

        Socket clientSocket = null;

        while (true) {
            clientSocket = serverSocket.accept();

            new HttpWebServer().handleRequest(clientSocket);

        }


    }

    private void handleRequest(Socket clientSocket) throws IOException {
        System.out.println("Received a http request with data as follows");

        InputStream socketInputStream = clientSocket.getInputStream();

        BufferedReader br = new BufferedReader(new InputStreamReader(
                socketInputStream));
        String line = null;
        String url = null;
        String method = null;
        StringBuilder isStringBuilder = new StringBuilder();

        while ((line = br.readLine()) != null) {

            isStringBuilder.append(line).append("\r\n");

            if (url == null && !line.isEmpty()) {
                method = line.split("\\ ")[0];
                url = line.split("\\ ")[1];
            }


            if (!br.ready())
                break;

        }

        System.out.println(isStringBuilder.toString());

        if (url != null && (method != null) && method.trim().equals(GET_METHOD)) {
            if (url.trim().equals(ROOT_URL))
                handleGetRootRequest(clientSocket);
            else if (url.trim().equalsIgnoreCase(FAV_ICON_URL))
                handleGetIconRequest(clientSocket);
        }

        /*
         * byte[] bytes = new byte[1024];
         * 
         * int count = 0;
         * 
         * do{ count = socketInputStream.read(bytes); String output = new
         * String(bytes, 0, count); System.out.print(output);
         * System.out.flush();
         * 
         * //count = socketInputStream.read(bytes); System.out.println(count);
         * 
         * }while(socketInputStream.available() > 0);
         */
        System.out.println("Completed processing request");
    }



    private void handleGetIconRequest(Socket clientSocket) {
        System.out.println("Yet to implement !!");
    }



    private void handleGetRootRequest(Socket clientSocket) throws IOException {

        OutputStream clientOS = clientSocket.getOutputStream();

        StringBuilder sb = new StringBuilder();

        sb.append("HTTP/1.1 200 OK ").append("\r\n").append("\r\n")
                .append("<TITLE>").append("SUCCESS").append("</TITLE>");

        String response = sb.toString();

        clientOS.write(response.getBytes("UTF-8"));
        clientOS.flush();
        clientOS.close();
        clientSocket.close();

    }

}

客户端:

package com.test.http.client;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;

public class HttpSimpleClient {


    public static void main(String[] args) throws UnknownHostException, IOException{

        Socket socket = new Socket("localhost",8081);

        StringBuilder requestBuilder = new StringBuilder();

        requestBuilder.append("GET")
        .append(" / ").append("HTTP/1.1").append("\r\n")
        .append("Connection: keep-alive").append("\r\n").append("\r\n")
        .append(" Some Body");

        OutputStream socketOutputStream = socket.getOutputStream();

        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socketOutputStream));

        bw.write(requestBuilder.toString());
        bw.flush();


        System.out.println("<Client> Send:"+ requestBuilder.toString());



        BufferedReader br = new BufferedReader(new InputStreamReader(
                socket.getInputStream()));

        StringBuilder responseBuilder = new StringBuilder();
        String line = null;

        while((line = br.readLine()) != null){

            responseBuilder.append(line);

            if(!br.ready()){
                break;
            }
        }

        System.out.println(" Response: "+requestBuilder.toString());

        socket.close();
    }
}

bw.flush();关闭Socket本身之后关闭bw,同时读取输入流时出错。

1 个答案:

答案 0 :(得分:2)

您应该阅读请求标题的末尾。那是"\r\n\r\n"序列。

while ((line = br.readLine()) != null) {
    isStringBuilder.append(line).append("\r\n");
    if (url == null && !line.isEmpty()) {
        method = line.split("\\ ")[0];
        url = line.split("\\ ")[1];
    }
    if (line.isEmpty())
        break;
}

如果您想阅读请求正文Some body。您必须将Content-Length: LENGTH_OF_BODY添加到请求标头中。服务器解析它,然后阅读LENGTH_OF_BODY 字节。在这种情况下,您无法使用BufferedReader