一般当浏览器发送完 Request 之后就会半关闭 socket ,这会使得服务器中read()
返回 0 ,服务器就知道 Request 已经读完了,然后根据 Request 可以生成 Response ,然后发回浏览器去(貌似是这样的吧?)
如果 Request 中有 Keep-alive 的话,浏览器就不会关闭 socket ,那么服务器中的read()
将会阻塞(阻塞状态)或者返回负值(非阻塞状态)。在这种情况下,服务器如果得知 Request 已经发送完了呢?是 Request 里面有长度信息吗?
本人对于 HTTP 理解不是很透彻,望大神答疑解惑。
1
vietor 2016-02-06 18:39:47 +08:00 via Android
分析已接收内容,头和 content-length
|
2
jasontse 2016-02-06 18:48:13 +08:00 via iPad
Header 传送完毕时会有两个 \n
|
3
rcmerci 2016-02-06 18:56:04 +08:00
不是应该 浏览器发完 request 后等着 response ,等到了就把 socket 关了。
要是发完 request 就关 socket 还怎么读 response 呀。 另外, request 结尾有 2 个\n |
4
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 |
5
qgy18 2016-02-06 19:37:01 +08:00 via iPhone
|
6
KyL OP @rcmerci 所以我设想的是半关闭,不能再写了,但是可以读吧?
另外, HTTP Request 中除了结尾之外,还有其他地方有两个\n 吗?比如 header 和 body 之间? |
7
rcmerci 2016-02-06 19:48:08 +08:00
@KyL 啊啊啊。。之前打错字了,是 header 结尾 2 个\n ,不是 request ,另外就像其他几位说的,根据 content-length (或者有其他什么字段吧) 来确定 request 有没有读完。
|
8
wowpanda 2016-02-06 19:49:49 +08:00 via Android
返回 0 呀
|
9
wowpanda 2016-02-06 19:52:10 +08:00 via Android
再配合 content-length
|
11
KyL OP @qgy18 拜读了,对从服务器发送到浏览器解释的很详细。那么从浏览器发送到服务器的持久化连接就只能靠 content-length 来实现吗?还是也可以用 chunked 来实现?
|
12
Strikeactor 2016-02-06 20:04:43 +08:00
不是判断它是不是完了的问题,他既然说了 Keep-alive 就表示“后边还有”, socket 在超时被关闭以前都可能还有东西进来
至于判断一个 HTTP Request 是不是完了,那是 HTTP 协议的事情,跟你 socket 的 read 读不读 0 是没有关系的 |
14
wowpanda 2016-02-06 20:59:30 +08:00
@KyL 额,返回 0 又不是非得关闭 socket 好不,写完一次数据就返回 0 ,至于 request 的所有长度是多少,那你得 read 一次之后就去计算一下已经 read 的数据总量是不是等于 content_length 。
read 返回 0 ,这表示要么 socket 关闭,要么是一次 send 的数据读完,也就是遇到了 EOF 。 |
15
wowpanda 2016-02-06 21:01:26 +08:00
写完一次数据->读完
|
16
KyL OP @wowpanda read 怎么会返回 0 呢。要么阻塞要么返回负值,只有对面关 socket 才会返回 0 吧?难道我记错了?
|
17
KyL OP 我目前在写一个 http server 。一开始打算先把 Request 都读出来,然后再解析 http 。但是有 keep-alive 后,看来就必须边读边解析了。这样 socket IO 代码就和 http 代码混在一起了。不知道 Apache 、 ngnix 都是怎么实现的。
|
18
denghongcai 2016-02-07 16:02:50 +08:00
@KyL websocket 是先用 http 协议请求升级,然后建立一条新的 TCP 连接,并不是和 http 的连接共用的
|
19
julyclyde 2016-02-18 13:46:23 +08:00
RFC 里写的明白
开启 Keep-Alive 时,必须启用 Content-Length 或者 Transfer-Encoding:chunked ,后两者都是可以明确表达长度的 |