python - 尝试通过 python 套接字升级到 http2
问题描述
我正在尝试使用 python 套接字升级到 http/2.0。我已经尝试过像这样使用升级标头:Connection: Upgrade
then 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。
我试过使用h2c
http/2.0
and 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,
我的问题是:为什么它只是挂起,我该如何解决?
解决方案
我认为您的一些异常处理给了您错误的提示。如果您遇到异常,您会一直在尝试再次连接,并且在某些时候 Windows 抱怨尝试连接到未关闭的套接字。
HTTP/2 的 ALPN 协议应设置为h2
,然后运行您的代码给我一个错误:
ValueError: check_hostname requires server_hostname
添加该参数后,我能够从服务器获得响应,Python 说连接是 H2:
import socket
import ssl
def connect_h2_socket(host):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
context = ssl.create_default_context()
context.set_alpn_protocols(["h2"])
sock.connect((host, 443))
sock = context.wrap_socket(sock, server_hostname=host)
return sock
s = connect_h2_socket("twitter.com")
print("Selected protocol:", s.selected_alpn_protocol())
print(s.recv())
运行它会为我产生以下结果:
Selected protocol: h2 b'\x00\x00\x06\x04\x00\x00\x00\x00\x00\x00\x04\x00\x01\x00\x00'
推荐阅读
- javascript - 我想以 PDF 格式打印 TinyMCE 区域的内容
- postgresql - postgres:错误:数据库不存在(psql 创建用户案例敏感性问题)
- javascript - REACT : all method in class are run 2 time
- authentication - NestJs GRPC - 如何在使用 nestjs 时设置 grpc 客户端拦截器
- javascript - 使用 Node FS 将大型 CSV 写入 JS 文件
- image - 为什么 Markdown 不能正确对齐图像?
- c++ - AVL 树遍历和重新平衡问题
- c++ - 在 C++ 中,如何为静态函数调用的函数获取 EXPECT_CALL()
- javascript - 反应 useEffect 以获取一次 Firestore 数据
- r - R:如何使偏移标签在动画期间不显示小数位