浏览器如何知道哪个响应对应哪个请求?

11

假设当我们通过HTTP请求资源时,我们会获得以下响应:

GET / HTTP/1.1
Host: www.google.co.in

HTTP/1.1 200 OK
Date: Thu, 20 Apr 2017 10:03:16 GMT
...

但是当浏览器一次请求多个资源时,它如何识别哪个请求得到了哪个响应?


Translated text:

But when a browser requests many resources at a time, how can it identify which request got which response?


它不需要“识别”那个,请求和响应会自动“配对”在一起。 - CBroe
服务器是否按顺序响应,以便通知浏览器?这意味着HTTP没有优先级。 - Ajender Reddy
不,请求可以并行进行。客户端只需打开多个连接,并通过每个连接发送一个HTTP请求,以便响应通过同一连接到达。http://blog.catchpoint.com/2010/09/17/anatomyhttp/解释了基础知识。 - CBroe
5个回答

19
当浏览器同时请求多个资源时,它如何识别哪个请求得到了哪个响应?
浏览器可以打开一个或多个连接到Web服务器以请求资源。对于这些连接,关于HTTP keep-alive的规则是相同的,并且适用于HTTP 1.0和1.1。
  • If HTTP keep-alive is off, the request is sent by the client, the response is sent by the server, the connection is closed:

    Connection 1: [Open][Request1][Response1][Close]
    
  • If HTTP keep-alive is on, one "persistent" connection can be reused for succeeding requests. The requests are still issued serially over the same connection, so:

    Connection 1: [Open][Request1][Response1][Request3][Response3][Close]
    Connection 2: [Open][Request2][Response2][Request4][Response4][Close]
    

HTTP 1.1引入了HTTP Pipelining,如果启用(大多数浏览器默认禁用,因为存在错误的服务器),浏览器可以连续发送请求而无需等待响应,但响应仍按照请求顺序返回。

  • This can happen simultaneously over multiple (persistent) connections:

    Connection 1: [Open][Request1][Request2][Response1][Response2][Close]
    Connection 2: [Open][Request3][Request4][Response3][Response4][Close]
    

保持连接和流水线两种方法仍然利用HTTP的默认“请求-响应”机制:每个响应将按照在同一连接上的请求顺序到达。它们还存在"排队阻塞"问题:如果[Response1]速度慢和/或很大,它会阻塞该连接后续的所有响应。

它通过为每个片段分配一个标识符来指示它属于哪个请求-响应对,以便接收者可以重新组合消息。

什么可以确保我发送的请求1、请求2和请求3按照我发送的顺序到达? - FabioThorin
1
@Fabio 没有任何东西能确保这一点。 - CodeCaster

2
我认为你真正想要的是HTTP Pipelining。这是在HTTP/1.1中引入的一种技术,通过该技术,客户端会按顺序发送所有请求,并且服务器会按照相同的顺序进行响应。所有详细信息现在都在RFC 7230, sec. 6.3.2中。
HTTP/1.0有一个类似的方法,称为Keep Alive。这将允许客户端在前一个请求得到回答后立即发出新的请求。这种方法的好处在于客户端和服务器不再需要通过另一个TCP握手来协商新的请求/响应周期。
重要的是,在两种方法中,响应的顺序与在一个连接上发出的请求的顺序相匹配。因此,通过客户端接收它们的顺序,可以将响应唯一地映射到发出的请求:第一个响应与第一个请求匹配,第二个响应与第二个请求匹配,以此类推。

HTTP/1.1的管线化(依赖KeepAlive)与HTTP/1.0的区别在于,在前者中,客户端可以在获得任何响应之前发出多个请求,而在HTTP/1.0中,客户端必须等待响应才能发出新的请求。 - symcbean
@symcbean 不对。HTTP / 1.1的流水线不依赖于Keep Alive,请参见上面的链接。 HTTP只是假定连接保持打开状态,直到关闭为止。关于请求/响应顺序:这基本上就是我写的,不是吗? - DaSourcerer
"不依赖于Keep Alive" - 我完全被这个搞糊涂了。如果只允许单个请求和响应的通道上如何发送多个请求? - symcbean
@symcbean 的方法很简单。你需要将这些请求“塞”给服务器(这么说吧),并确保在最后一个请求中不发送 Connection: close 头部信息。这样服务器仍然有自由选择只回答第一个请求或者前 n 个请求,具体取决于服务器能够承受的负载大小。 - DaSourcerer

2
我认为你所寻找的答案是TCP
HTTP是一种协议,它依赖于TCP来建立客户端主机之间的连接。
HTTP/1.0中,每个请求/响应对都需要创建一个不同的TCP连接。 HTTP/1.1引入了流水线技术,允许多个请求/响应对重用单个TCP连接以提高性能(但效果并不理想)。
因此,请求和相应通过它们所依赖的TCP连接进行关联。
这样就很容易将特定的请求与其生成的响应相关联。
PS:HTTP并非永远绑定于使用TCP,例如Google正在尝试使用其他传输协议,如QUIC,这可能比TCP更适合HTTP的需求,并能提高效率。

1
除了上述解释外,还需考虑浏览器可以打开许多并行连接,通常最多可到同一服务器的6个连接。对于每个连接,它使用不同的套接字。对于每个套接字中的每个请求-响应,很容易确定其相关性。

0
在每个TCP连接中,请求和响应是按顺序进行的。在完成请求-响应周期后,可以重用TCP连接。 通过HTTP pipelining,可以将单个连接多路复用以实现多个重叠请求。 理论上,可以有任意数量[*1]的同时TCP连接,以实现并行请求和响应。 实际上,同时连接的数量通常在浏览器上有限制,而且服务器上也经常有限制。
[*1] 同时连接数受浏览器能够分配于给定系统上的短暂TCP端口数量的限制。根据操作系统的不同,短暂端口从1024(RFC 6056)、49152(IANA)或32768(某些Linux版本)开始。
因此,这可能允许一个应用程序最多使用 65,535 - 1023 = 64,512 个 TCP 源端口。 TCP 套接字连接由其本地端口号、本地 IP 地址、远程端口号和远程 IP 地址定义。假设服务器使用单个 IP 地址和端口号,则限制是您可以使用的本地端口数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接