6

我刚刚写了一个小程序来测试一些东西,如下:

public class Main {

    public static void main(String[] args){
        ServerSocket serverSocket = null;
        Socket clientSocket = null;
        DataInputStream dataInputStream= null;

        BufferedWriter bufferedWriter = null;
        String line ;

        try {
            serverSocket = new ServerSocket(80);
            clientSocket = serverSocket.accept();

            dataInputStream = new DataInputStream(clientSocket.getInputStream());

            while((line = dataInputStream.readLine()) != null){
                System.out.println(line);
            }

            bufferedWriter = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
            bufferedWriter.write("HTTP/1.0 200 OK \n Date: Fri, 31 Dec 1999 23:59:59 GMT \n Content-Type: text/html \n Content-Length: 1354 \n <html>abcde<html/>");

            bufferedWriter.flush();

        } catch (IOException e) {
            System.out.println("socket port cannot be opened.");
            e.printStackTrace();
        } finally{
            try {
                serverSocket.close();
                bufferedWriter.close();
            } catch (IOException e) {
                System.out.println("socket port cannot be closed.");
                e.printStackTrace();
            }
        }


    }

}

我从网上找到了http响应格式,应该是正确的。问题是我的浏览器一直在等待响应数据(从旋转的标志确定),但数据没有返回成功。我犯了什么错误?

我通过在浏览器中键入“localhost”连接到 Java 程序,我可以在 Java 程序中打印出请求字符串,但只是无法发回响应。

4

3 回答 3

3

首先,发送的 HTTP 消息存在一些问题:HTTP 消息的每一行都由 CR LF 分隔/结束,而不仅仅是换行(虽然我怀疑这可能是问题,你应该替换“ \n" 与 "\r\n")。另外,Content-Length 不等于消息体的实际大小,应该替换。在实际正文之前,所有 HTTP 消息都应该有一个空行,而您没有。最后,正斜杠 at<html/>也应该出现在 之前html,如下所示:</html>

总结一下:

bufferedWriter.write("HTTP/1.0 200 OK\r\nDate: Fri, 31 Dec 1999 23:59:59 GMT\r\nContent-Type: text/html\r\nContent-Length:18\r\n\r\n<html>abcde</html>");

现在是真正的问题:读取循环一直在等待更多数据。将 readLine() 的结果与 null 进行比较实际上并不能满足您的要求。TCP 连接产生数据流,您永远不知道客户端是否在特定时刻停止发送数据。相反,您可以一直阅读,直到找到一个空行,这标志着 HTTP 消息头部的结束。Web 浏览器通常不会在 GET 消息中发送附加内容,因此您不会丢失任何数据。

    BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    while(!(line = reader.readLine()).isEmpty()){
        System.out.println(line);
    }
于 2012-08-03T17:20:07.340 回答
3

可能是 Content-Length 标头字段吗?尝试用这个替换响应:

bufferedWriter.write("HTTP/1.0 200 OK \n Date: Fri, 31 Dec 1999 23:59:59 GMT \n Content-Type: text/html \n Content-Length: 18\n <html>abcde<html/>");

(注意Content-Length: 18与原来的对比Content-Length: 1354

我怀疑浏览器正在等待您的应用程序发送更多数据。

编辑:这对我有用:

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

public class Main {

    public static void main(String[] args) throws Exception{
        ServerSocket serverSocket = null;
        Socket clientSocket = null;
        DataInputStream dataInputStream= null;

        BufferedWriter bufferedWriter = null;

        try {
            serverSocket = new ServerSocket(8080);
            clientSocket = serverSocket.accept();

            BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

            while (clientSocket.getInputStream().available() > 0) {
                String line = reader.readLine();

                if (line == null) {
                    break;
                }

                System.out.println(line);
            }

            bufferedWriter = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
            bufferedWriter.write("HTTP/1.0 200 OK \n Date: Fri, 31 Dec 1999 23:59:59 GMT \n Content-Type: text/html \n\n <html>abcde<html/>");
            bufferedWriter.flush();
            clientSocket.close();
        } catch (IOException e) {
            System.out.println("socket port cannot be opened.");
            e.printStackTrace();
        } finally{
            try {
                serverSocket.close();
                bufferedWriter.close();
            } catch (IOException e) {
                System.out.println("socket port cannot be closed.");
                e.printStackTrace();
            }
        }


    }

}

罪魁祸首是while循环。您为获取更多数据而调用的方法一直处于阻塞状态,直到该数据可用(这永远不会发生)。我不确定我所做的是否完全有必要,但它确实有效。

于 2012-08-03T17:16:33.697 回答
1

我看到两个问题:

content-length 标头说后面是 1354 个字节。你只写了20个左右。内容长度是可选的;如果您没有使用正确的值,请不要包含它。

您需要在标题末尾和内容之前有一个空行:".... Content-Length: xx\n\n<html>..."

于 2012-08-03T17:19:45.030 回答