gpt4 book ai didi

java - 简单的 Web 服务器在收到 http 请求时挂起

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:26:17 26 4
gpt4 key购买 nike

我正在写一个简单的网络服务器,代码片段:

 ServerSocket server = new ServerSocket(80);  
Socket client=server.accept();
InputStream in=client.getInputStream();
OutputStream out=client.getOutputStream();
int val = -1;
while ((val = in.read()) != -1) {
System.out.print((char) val);
}
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter( out));
writer.write("HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\nhello world!");
writer.close();
out.close();
in.close();

我在我的电脑上运行它,然后访问http://127.0.0.1在火狐中。页面挂起,无法显示“hello world”。我认为问题出现在while ((val = in.read()) != -1),如何解决?

最佳答案

HTTP(至少是 1.1 版本)允许打开连接。如果请求不是包含内容的 POST 或 PUT 请求,则请求以空行结束(即 "\r\n\r\n")。此后,客户端可以在同一连接上发送下一个请求。

因此您至少必须阅读输入以扫描空行。


编辑:为了澄清这一点,引用了 RFC 2616 中的一些内容(它定义了 HTTP 1.1)。

4.1 节,消息类型:

Request (section 5) and Response (section 6) messages use the generic message format of RFC 822 [9] for transferring entities (the payload of the message). Both types of message consist of a start-line, zero or more header fields (also known as "headers"), an empty line (i.e., a line with nothing preceding the CRLF) indicating the end of the header fields, and possibly a message-body.

   generic-message = start-line
*(message-header CRLF)
CRLF
[ message-body ]
start-line = Request-Line | Status-Line

因此,消息头和消息正文由一个空行(开始行之后的第一个)分隔。

4.3 消息正文部分:

The message-body (if any) of an HTTP message is used to carry the entity-body associated with the request or response. [...]

The rules for when a message-body is allowed in a message differ for requests and responses.

The presence of a message-body in a request is signaled by the inclusion of a Content-Length or Transfer-Encoding header field in the request's message-headers. A message-body MUST NOT be included in a request if the specification of the request method (section 5.1.1) does not allow sending an entity-body in requests. A server SHOULD read and forward a message-body on any request; if the request method does not include defined semantics for an entity-body, then the message-body SHOULD be ignored when handling the request.

因此原则上,客户端只能在方法允许的情况下发送消息体,但服务器应该忽略多余的消息体,如果它们是在不支持它的方法上发送的。主体的存在由 Content-LengthTransfer-Encoding header 字段指示。

第 9 节的小节定义了各个方法。

  • 9.2 选项
    • 可以包含正文,但意义未定义
  • 9.3 获得
    • 不能包含正文
  • 9.4 头
    • 不能包含正文
  • 9.5 后
    • 应该(或必须?)包含一个正文
  • 9.6 分
    • 应该(或必须?)包含一个正文
  • 9.7 删除
    • 不能包含正文
  • 9.8 微量
    • 不能包含正文
  • 9.9 连接
    • (此方法保留)

无论如何,无论客户端是否发送主体,以及是否为下一个请求重用连接,它通常不会在读取响应之前关闭连接,否则您的服务器将无法重新发送完全没有反应。因此,您根本无法在阅读请求时等待关闭,而是必须以某种方式知道它何时结束才能发送您的响应。

对于只处理 get 请求的简单 hello world 服务器,您可以简单地说“读到第一个空行”。

对于真实的服务器(即对外界可见的服务器),您至少应该解析请求,忽略任何主体,并以不同于 GET 的方式处理 HEAD(即不发回任何主体),然后发送不支持的方法的错误响应。

关于java - 简单的 Web 服务器在收到 http 请求时挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5485800/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com