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

2016 年 2 月 6 日
 KyL

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

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

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

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

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

https://study.congcong.us/t/255671

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

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

© 2021 V2EX