【问题标题】:Do websocket implementations use http protocol internally?websocket 实现是否在内部使用 http 协议?
【发布时间】:2018-04-15 13:35:41
【问题描述】:

为了建立 WebSocket 连接,客户端发送一个 WebSocket 握手请求,服务器为此返回一个 WebSocket 握手响应,如下例所示。[30]

客户端请求(就像在HTTP中一样,每行以\r\n结尾,并且末尾必须有一个额外的空行):

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com

服务器响应:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat

我无法理解。为了初始化连接,发送 HTTP GET 请求。但是如果我不托管 HTTP 服务器而只托管 WebSocket 服务器呢?那么它是如何处理 HTTP 请求的呢?

【问题讨论】:

    标签: sockets websocket


    【解决方案1】:

    根据设计,WebSocket 协议握手使用 HTTP,因此 WebSocket 可用于现有 HTTP 服务器和其他基于 HTTP 的技术:

    WebSocket 协议旨在取代使用 HTTP 作为传输层的现有双向通信技术,以从现有基础设施(代理、过滤、身份验证)中受益。这些技术被实现为效率和可靠性之间的权衡,因为 HTTP 最初并不打算用于双向通信(请参阅 [RFC6202] 以获得进一步讨论)。 WebSocket 协议试图在现有 HTTP 基础设施的上下文中解决现有双向 HTTP 技术的目标;因此,它被设计为在 HTTP 端口 80 和 443 上工作,并支持 HTTP 代理和中介,即使这意味着特定于当前环境的一些复杂性。但是,该设计并未将 WebSocket 限制为 HTTP,未来的实现可以在专用端口上使用更简单的握手,而无需重新发明整个协议。最后一点很重要,因为交互式消息传递的流量模式与标准 HTTP 流量不匹配,并且会在某些组件上引发异常负载。

    但是,一旦 WebSocket 握手完成,就只使用 WebSocket 协议,不再使用 HTTP。

    因此,使用支持 WebSocket 的 HTTP 服务器或专用 WebSocket 服务器都没有关系。 任何 WebSocket 实现必须使用 HTTP(以及其中的所有语义,包括身份验证、重定向等)进行初始握手。它是由 WebSocket 协议规范 RFC 6455 强制执行的。

    打开握手旨在与基于 HTTP 的服务器端软件和中介兼容,以便 HTTP 客户端与该服务器通信和 WebSocket 客户端与该服务器通信都可以使用单个端口。为此,WebSocket 客户端的握手是一个 HTTP 升级请求

    因此,至少,专用的 WebSockets 服务器必须能够在握手阶段处理 HTTP 请求。实现起来并不难。

    【讨论】:

    • 太棒了!谢谢雷米!!
    【解决方案2】:

    websocket 实现内部是否使用 http 协议?

    是的,最初,他们切换到 webSocket 协议。所有 webSocket 连接都以带有请求升级到 webSocket 协议的标头的 HTTP 请求开始。如果接收服务器同意,则双方将协议从 HTTP 切换到 webSocket,然后连接使用 webSocket 协议。

    因此,所有 webSocket 服务器都必须支持初始 HTTP 请求,因为这就是所有 webSocket 连接的启动方式。

    webSocket 协议采用这种方式设计有几个原因:

    1. 因此,单个主机和端口可用于常规 HTTP 和 webSocket 连接。如果需要,您可以使用单个服务器进程来处理这两种类型的连接。如果它们在不同的端口上,您将需要两个单独的服务器进程。

    2. 1234563在常规 HTTP 端口上。

    如您所见,webSocket 请求以这样的 HTTP 请求开始:

    GET /chat HTTP/1.1
    Host: server.example.com
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
    Sec-WebSocket-Protocol: chat, superchat
    Sec-WebSocket-Version: 13
    Origin: http://example.com
    

    注意Upgrade: websocket 标头。这告诉接收 HTTP 服务器这是对 webSocket 连接的请求。如果服务器想要接受该连接,它会返回一个 101 响应,告诉客户端他们现在可以切换协议:

    HTTP/1.1 101 Switching Protocols
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
    Sec-WebSocket-Protocol: chat
    

    在此响应之后,客户端和服务器都切换协议(在同一个 TCP 连接上),从那时起,它们只使用 webSocket 协议,并且 TCP 连接保持打开状态,直到客户端或服务器明确关闭它(通常是长期连接) .

    我无法理解。为了初始化连接,发送 HTTP GET 请求。但是如果我不托管 HTTP 服务器而只托管 WebSocket 服务器呢?

    所有 webSocket 服务器都必须接受 HTTP 请求,因为所有 webSocket 连接都以 HTTP 请求开始。因此,不存在不接受 HTTP 请求的 webSocket 服务器。纯 webSocket 服务器只能接受带有 Upgrade: webSocket 标头的 HTTP 请求,而其他任何 HTTP 请求都失败。

    那么它是如何处理 HTTP 请求的呢?

    所有 webSocket 服务器都希望传入的新连接以 HTTP 开头,因此它们必须有一个简单的内置 HTTP 服务器(可以解析初始 HTTP 标头)。

    【讨论】:

      最近更新 更多