使用 Berkeley 套接字进行多路复用

Posted

技术标签:

【中文标题】使用 Berkeley 套接字进行多路复用【英文标题】:Multiplexing with Berkeley Sockets 【发布时间】:2014-09-03 10:42:47 【问题描述】:

我有一个使用 Berkeley 套接字用 C++ 编写的 Web HTTP/1.1 服务器实现。我正在考虑实现对 HTTP/2.0(或 SPDY)的支持,它允许请求和响应多路复用:

HTTP/2.0 中的二进制帧层支持完整的请求和响应多路复用,允许客户端和服务器将 HTTP 消息分解为独立的帧,交织它们,然后在另一端重新组合它们。

我的问题如下;如何启用 HTTP/2.0(或 SPDY)类型的请求和响应多路复用与使用 Berkeley Socket API 编写的现有 HTTP/1.1 程序?或许前面提到的 HTTP/2.0(或 SPDY)支持的帧复用已经被 TCP/IP Stack 中的现有机制处理了,或者?

澄清:

我对使用单个连接并行传递多个请求和响应的多路复用部分特别感兴趣,我从规范中不明白这是如何在应用程序中实现的层协议?有什么想法吗?

【问题讨论】:

SPDY 是一个不同的协议——除了“实现协议”之外,您在寻找什么答案? @janm TCP/IP 堆栈中有多种类型的多路复用,我正在寻找如何实现 HTTP/2.0(和 SPDY)支持的那种请求/响应多路复用的解决方案。 HTTP/2.0(或 SPDY)协议的其余部分不在当前问题的范围内。谢谢。 SPDY 不在 TCP/IP 堆栈中,它在 TCP 之上,传统上它会被认为是一个应用程序协议。它的控制和数据框架记录在草案规范中。您通过实现协议来实现多路复用。你读过协议草案吗? @mrjoltcola 是的,我知道 HTTP/2.0(或 SPDY)不是 TCP/IP 堆栈的一部分,我从未暗示它是。你能添加一个链接到你提到的多路复用协议实现协议吗? -TIA 请原谅我的困惑,但您帖子中的最后一句话似乎对我暗示了这一点。不管怎样,看我的回答。 【参考方案1】:

不,TCP 堆栈不处理任何这些,因为 SPDY 不是 TCP/IP 堆栈的一部分,它位于 TCP 之上,传统上被认为是应用程序协议。它的控制和数据框架记录在草案规范中。您通过实现协议来实现多路复用。 TCP 堆栈对 HTTP 或 SPDY 一无所知。

简而言之,SPDY 由单个 TCP 连接中的帧组成,其中包括相当简单的标头以及会话 ID 和帧长度等。您必须实现它才能进行多路复用。您应该能够使用标准的启用 SSL/TLS 的套接字代码来实现这一切。

据我所知,这是规范 -

http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft2

【讨论】:

use a single connection to deliver multiple requests and responses in parallel 的多路复用部分怎么样,我从规范中不明白这是如何在应用程序级协议中实现的?有什么想法吗? @IngeHenriksen 您提供的链接显示了 SPDY 如何允许使用单个 TCP 连接同时存在多个“流”。这是通过 SPDY 成帧识别哪些数据属于哪个流来完成的。混淆可能来自术语“并行”——​​在单个 TCP 连接中,来自不同流的帧必须一个接一个地出现,但并不要求一个流在另一个流开始之前完成。 因此,您按顺序一次读取一帧,查看每个帧头以了解它属于哪个流,并根据需要缓冲/解析每个帧的数据。当您到达给定流上的请求的最后一帧时,处理该流的缓冲区并根据需要发送响应,类似地将响应数据与其他流的响应并行构建。您需要实现流的并行处理,而不是帧的并行处理。帧需要被序列化,因此帧不会在每个方向上重叠。为一个流发送帧,从另一个流发送帧,等等。 @amaninlove 如果发送确实失败,则 TCP 连接的状态是不确定的,因此唯一可行的选择是关闭连接并重新开始一个新连接。但是,如果发送仅发送比请求更少的字节,那么是的,您必须重新发送剩余的字节,不,您不需要重新构建数据。只需完成发送您已开始发送的帧。在前一帧完成之前不要开始发送新帧。接收端也一样。读取一整帧,无论完成多少次读取,然后处理该帧,然后读取下一帧,等等。 @amaninlove 这意味着您没有正确管理您的读取/发送。再仔细阅读我之前的cmets,我已经厌倦了重复自己。你不能按照你描述的方式做事。在发送新帧之前,您必须完整发送一个帧(可能需要多次写入)。在接收下一帧之前,您必须完整接收一帧(可能需要多次读取)。如果发送方想要发送一个新的帧,而之前的帧仍在忙于发送,则它必须将新帧延迟到稍后的时间。将其放入队列中,然后按顺序发送排队的帧。

以上是关于使用 Berkeley 套接字进行多路复用的主要内容,如果未能解决你的问题,请参考以下文章

I/O多路复用-EPOLL探索

TCP的多路复用和分解

IO多路复用机制(转)

多路复用之selectepollpoll

Linux IO多路复用

套接字连接可以多路复用吗?