【发布时间】:2021-06-29 17:26:29
【问题描述】:
我正在尝试使用 python 套接字升级到 http/2.0。我已经尝试过像这样使用升级标头:Connection: Upgrade 然后Upgrade: h2c。这使服务器响应 http/1.1 200 OK 响应。我现在正在尝试通过 ssl 模块使用 ALPN。
这是通过 ALPN 尝试的代码:
def connect_socket(self):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
context = ssl.create_default_context()
context.set_alpn_protocols(['h2c'])
while True:
try:
sock.connect(("twitter.com", 443))
sock = context.wrap_socket(sock)
return sock
except:
pass
这只是挂在context.wrap_socket(sock)。如果我摆脱上下文并只使用ssl.wrap_socket() 一切正常,我可以使用 HTTP/1.1 很好。服务器确实支持它,因为使用 PyCurl 的详细模式我可以看到它使用 HTTP/2。
我试过使用h2chttp/2.0和h2。
打印我得到的异常,结果是这样的:
[WinError 10056] A connect request was made on an already connected socket
仍未升级的最新代码:
def connect_socket(self):
while True:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
context = ssl.create_default_context()
context.set_alpn_protocols(['h2c'])
context.check_hostname = False
try:
sock.connect(("twitter.com", 443))
sock = context.wrap_socket(sock)
return sock
except Exception as e:
sock.close()
print(e)
这会返回一个没有错误的套接字,然后发送这个请求:
def test_send_data(self, sock):
unencoded_string = 'GET /noah HTTP/1.1\r\nHost: twitter.com\r\nConnection: keep-alive\r\n\r\n'
sock.send(unencoded_string.encode())
这发送很好,响应的重要部分是这样的:
HTTP/1.1 200 OK\r\ncache-control: no-cache, no-store, must-revalidate,
我的问题是:为什么它只是挂起,我该如何解决?
【问题讨论】:
-
与
'h2c'相比,'h2'有什么改变吗? -
不,事实证明我遇到了异常。详情请查看已编辑的问题。
-
while 循环是怎么回事?我相信你首先遇到了一个不同的异常,它传递了异常,然后当你再次连接时你会发现你已经在套接字上,因为你处于一个循环中。
-
哎呀,在最近的评论之前不小心删除了我的评论,后人是“将
server_hostname="twitter.com"传递给wrap_socket并使用h2作为协议。应该没问题。摆脱while循环并且不要传递你的异常。” -
事实证明你是对的。使用 h2 而不是检查主机名对我来说会挂起,但传递 server_hostname 会起作用。在那之后,我的下一个错误实际上是在我正在寻找 \r\n\r\n 以打破读取循环并返回字节字符串的 recv 函数中。我刚刚意识到这不起作用,在打印套接字接收数据后如果你愿意,发布答案,我会接受+投票。