一般当浏览器发送完 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 ,后两者都是可以明确表达长度的 |