草庐IT

Golang TCP 服务器读取 HTTP/2 帧

coder 2024-07-11 原文

我正在尝试设置一个接受和解码 HTTP/2 数据的 TCP 服务器。实际解析帧的代码可以在这篇文章中找到:

Decoding http2 frame header/data in Go

但是,我在设置服务器时遇到了问题。连接被接受,但它卡在 framer.ReadFrame() 上。这是一个代码示例:

// generate with: openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.pem -days 365 -nodes
cert, err := tls.LoadX509KeyPair("server.pem", "server.key")
if err != nil {
    log.Fatal(err)
}

tlsCfg := &tls.Config{
    Certificates: []tls.Certificate{cert},
    NextProtos:   []string{"h2"},
}

l, err := tls.Listen("tcp", ":8787", tlsCfg)
if err != nil {
    log.Fatal(err)
}
defer l.Close()

conn, err := l.Accept()
if err != nil {
    log.Fatalln(err)
}
defer conn.Close()

framer := http2.NewFramer(conn, conn)
frame, _ := framer.ReadFrame() // Here it hangs

我使用curl请求服务器

curl -v https://127.0.0.1:8787/ -k --http2

最佳答案

对话 doesn't start with a frame .首先客户端发送字符串

"PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"

您可以通过检查客户端发送的字节来判断:

framer := http2.NewFramer(conn, io.TeeReader(conn, hex.Dumper(os.Stdout)))

// 00000000  50 52 49 20 2a 20 48 54  54 50 2f 32 2e 30 0d 0a  |PRI * HTTP/2.0..|
// 00000010  0d 0a 53 4d 0d 0a 0d 0a  00 00 12 04 00 00 00 00  |..SM............|
// 00000020  00 00 03 00 00 00 64 00  04 40 00 00 00 00 02 00  |......d..@......|
// 00000030  00 00 00 00 00 04 08 00  00 00 00 00 3f ff 00 01  |............?...|
// 00000040  00 00 1e 01 05 00 00 00  01 82 84 87 41 8a a0 e4  |............A...|
// 00000050  1d 13 9d 09 b8 f3 af 3b  7a 88 25 b6 50 c3 ab b6  |.......;z.%.P...|
// 00000060  fa e0 53 03 2a 2f 2a ^C

如果您修改代码以首先读取该字符串,它会按预期工作:

conn, err := l.Accept()
if err != nil {
    log.Fatalln(err)
}   
defer conn.Close()

const preface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
b := make([]byte, len(preface))
if _, err := io.ReadFull(conn, b); err != nil {
    log.Fatalln(err)
}
if string(b) != preface {
    log.Fatalln("invalid preface")
}

framer := http2.NewFramer(conn, conn)
frame, err := framer.ReadFrame()
fmt.Println(frame, err)

// Output:
// [FrameHeader SETTINGS len=18] <nil>

如果发现这些文章在我自己使用 HTTP2 时有用:

关于Golang TCP 服务器读取 HTTP/2 帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51981111/

有关Golang TCP 服务器读取 HTTP/2 帧的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  4. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  5. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  6. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  7. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  8. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  9. ruby-on-rails - 在 Rails 中调试生产服务器 - 2

    您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除

  10. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

随机推荐