如果浏览器发送的 HTTP Request 中使用了 Keep-alive,服务器如何得知这个 Request 已经读取完成?

2016-02-06 18:18:49 +08:00
 KyL

一般当浏览器发送完 Request 之后就会半关闭 socket ,这会使得服务器中read()返回 0 ,服务器就知道 Request 已经读完了,然后根据 Request 可以生成 Response ,然后发回浏览器去(貌似是这样的吧?)

如果 Request 中有 Keep-alive 的话,浏览器就不会关闭 socket ,那么服务器中的read()将会阻塞(阻塞状态)或者返回负值(非阻塞状态)。在这种情况下,服务器如果得知 Request 已经发送完了呢?是 Request 里面有长度信息吗?

本人对于 HTTP 理解不是很透彻,望大神答疑解惑。

4621 次点击
所在节点    HTTP
19 条回复
vietor
2016-02-06 18:39:47 +08:00
分析已接收内容,头和 content-length
jasontse
2016-02-06 18:48:13 +08:00
Header 传送完毕时会有两个 \n
rcmerci
2016-02-06 18:56:04 +08:00
不是应该 浏览器发完 request 后等着 response ,等到了就把 socket 关了。
要是发完 request 就关 socket 还怎么读 response 呀。
另外, request 结尾有 2 个\n
jybox
2016-02-06 18:58:11 +08:00
一种情况是一楼说的 Content-Length, 还有一种是 Transfer-Encoding=chunked
详见 https://zh.wikipedia.org/wiki/%E5%88%86%E5%9D%97%E4%BC%A0%E8%BE%93%E7%BC%96%E7%A0%81
qgy18
2016-02-06 19:37:01 +08:00
不得不安利一下我的这篇文章:
https://imququ.com/post/transfer-encoding-header-in-http.html
KyL
2016-02-06 19:39:07 +08:00
@rcmerci 所以我设想的是半关闭,不能再写了,但是可以读吧?
另外, HTTP Request 中除了结尾之外,还有其他地方有两个\n 吗?比如 header 和 body 之间?
rcmerci
2016-02-06 19:48:08 +08:00
@KyL 啊啊啊。。之前打错字了,是 header 结尾 2 个\n ,不是 request ,另外就像其他几位说的,根据 content-length (或者有其他什么字段吧) 来确定 request 有没有读完。
wowpanda
2016-02-06 19:49:49 +08:00
返回 0 呀
wowpanda
2016-02-06 19:52:10 +08:00
再配合 content-length
KyL
2016-02-06 19:59:20 +08:00
@wowpanda 浏览器不关闭 socket ,服务器 read 怎么会返回 0 呢?
KyL
2016-02-06 20:04:42 +08:00
@qgy18 拜读了,对从服务器发送到浏览器解释的很详细。那么从浏览器发送到服务器的持久化连接就只能靠 content-length 来实现吗?还是也可以用 chunked 来实现?
Strikeactor
2016-02-06 20:04:43 +08:00
不是判断它是不是完了的问题,他既然说了 Keep-alive 就表示“后边还有”, socket 在超时被关闭以前都可能还有东西进来
至于判断一个 HTTP Request 是不是完了,那是 HTTP 协议的事情,跟你 socket 的 read 读不读 0 是没有关系的
qgy18
2016-02-06 20:42:04 +08:00
@KyL 应该也是可以的,但是浏览器发送的数据一开始很容易得到 Content-Length ,没必要 chunked 啊。
wowpanda
2016-02-06 20:59:30 +08:00
@KyL 额,返回 0 又不是非得关闭 socket 好不,写完一次数据就返回 0 ,至于 request 的所有长度是多少,那你得 read 一次之后就去计算一下已经 read 的数据总量是不是等于 content_length 。
read 返回 0 ,这表示要么 socket 关闭,要么是一次 send 的数据读完,也就是遇到了 EOF 。
wowpanda
2016-02-06 21:01:26 +08:00
写完一次数据->读完
KyL
2016-02-07 10:01:11 +08:00
@wowpanda read 怎么会返回 0 呢。要么阻塞要么返回负值,只有对面关 socket 才会返回 0 吧?难道我记错了?
KyL
2016-02-07 10:06:12 +08:00
我目前在写一个 http server 。一开始打算先把 Request 都读出来,然后再解析 http 。但是有 keep-alive 后,看来就必须边读边解析了。这样 socket IO 代码就和 http 代码混在一起了。不知道 Apache 、 ngnix 都是怎么实现的。
denghongcai
2016-02-07 16:02:50 +08:00
@KyL websocket 是先用 http 协议请求升级,然后建立一条新的 TCP 连接,并不是和 http 的连接共用的
julyclyde
2016-02-18 13:46:23 +08:00
RFC 里写的明白
开启 Keep-Alive 时,必须启用 Content-Length 或者 Transfer-Encoding:chunked ,后两者都是可以明确表达长度的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/255671

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX