【问题标题】:nghttpd connection closed automaticallynghttpd 连接自动关闭
【发布时间】:2018-11-15 21:35:21
【问题描述】:

我正在尝试使用 nghttpd 服务器来测试 HTTP/2.0。要启动它,我正在使用:

sudo nghttpd --push=/test=/test1.png,/test2.pcapng,/test2.txt,/test3.png  --no-tls --workers=3  --early-response  -v  80.

在我的 CWD 中,我有推送文件。在另一个终端中,我输入:

telnet localhost 80

一切似乎都很好,因为我在第一个终端有这个输出

[id=1] [ 11.893] send SETTINGS frame <length=6, flags=0x00, stream_id=0>
      (niv=1)
      [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
[id=1] [ 21.898] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
      (last_stream_id=0, error_code=SETTINGS_TIMEOUT(0x04), opaque_data(0)=[])

当我使用第二个终端尝试(任何类型的)HTTP GET 时会出现问题:

telnet localhost 80
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET /test HTTP/2.0
Connection closed by foreign host.

在我的第一个终端中,我得到了这个输出

[id=1] [314.531] closed

我该如何解决这个问题?

【问题讨论】:

    标签: telnet httpserver http2 nghttp2


    【解决方案1】:

    详细说明:HTTP/2 服务器发送控制帧,如 MAGICSETTINGS(这包括最大并发流和初始窗口大小等信息),并且服务器不接受客户端,直到这些被客户端确认客户端(也在SETTINGS 框架中)。

    Telnet 只是建立 TCP 连接,然后等待用户发出下一个数据包。

    在几秒钟内没有看到这些控制帧,服务器在几秒钟内关闭了连接。

    这是根据 RFC 7540,第 6.5.3 节:

    如果 SETTINGS 帧的发送者在合理的时间内没有收到确认,它可能会发出 SETTINGS_TIMEOUT 类型的连接错误(第 5.4.1 节)。

    这是我通过 Telnet 连接时 nghttpd(以详细模式运行)的日志:

    [id=2] [ 34.645] send SETTINGS frame <length=6, flags=0x00, stream_id=0>
              (niv=1)
              [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
    [id=2] [ 44.654] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
              (last_stream_id=0, error_code=SETTINGS_TIMEOUT(0x04), opaque_data(0)=[])
    [id=2] [ 44.654] closed
    

    其实你的问题就是答案,只是你部分打印了nghttpd服务器的日志。服务器在发送SETTINGS帧10秒后发送GOAWAY帧并关闭TCP连接。

    【讨论】:

    • 我只是在阅读 RFC 7540。由于 nghttpd 是一个测试服务器,我可以自定义它的要求,以便与一个空的 SETTINGS 框架建立连接(它说 0-7 参数,空 i意味着 0 参数)与 ack 集。我现在正在做这件事。 ack 是否应该在 TCP 信封中?有没有办法查看示例框架? 我正在尝试用谷歌搜索它,但我找不到任何东西。我正在尝试使用 wireshark 查看 HTTP/2 通信中的响应示例,但由于流量是加密的(TLS)
    • 您可以在 h2c 上运行 nghttp2。 $ nghttpd -a 127.0.0.1 --no-tls -d ./htdoc 8080
    【解决方案2】:

    HTTP/2 是二进制协议,您不能像使用 HTTP/1.1 那样使用 telnet

    您需要仔细阅读HTTP/2 specification,它描述了 HTTP/2 协议是二进制的,并且需要使用HPACK 压缩 HTTP 标头。 这两件事结合起来使得telnet 和手动输入到套接字变得非常困难;与 HTTP/2 服务器交互的常用方法是使用 HTTP/2 客户端工具。

    此类客户端工具包括nghttp 本身以及curl

    【讨论】:

    • 我解决了使用 curl 强制 http2(在安装 libcurl 之后),但我想自己构建和发送一个框架,如果可能的话,可能使用 nc 或 telnet
    • 有可能,只是您必须编写二进制数据,并且您必须自己弄清楚请求行和标题的 HPACK 编码 - 这是一些工作但可行。也许最好使用工具发送请求,使用tcpdump 或类似方法捕获网络跟踪,然后重放使用nctelnet 捕获的字节。
    猜你喜欢
    • 2012-02-21
    • 1970-01-01
    • 2023-03-03
    • 2014-10-25
    • 1970-01-01
    • 2021-12-16
    • 2020-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多