http 长连接
http/1.0默认不开启 connection:keep-alive
http/1.1默认开启
笔者想抓包测试一下http 1.1里面的长连接
一个简单的flask接口
# Flask==1.1.2
# Werkzeug==1.0.1
from flask import Flask, make_response
app = Flask(__name__)
@app.route('/hello', methods=['get'])
def hello():
res = make_response('hello world!')
return res
if __name__ == '__main__':
app.run(host='127.0.0.1', debug=True, port=5001)
postman发送请求,wireshark抓包(过滤条件: ip.addr==127.0.0.1 and tcp.port==5001)
下图首两行可以看到TCP协议,标志位SYN,握手报文。(深灰色)
倒数四行TCP协议,标志位FIN, 是挥手报文。(深灰色)
图里剩下的内容应用层http协议,这就是我们发送、响应的报文。(绿色)
即一次http请求、响应需要tcp完整握手与挥手,再发起一次http请求也是同样效果。
![](https://img.haomeiwen.com/i19069836/0ea85a9e8f24900a.png)
response header
![](https://img.haomeiwen.com/i19069836/cf90101169456a01.png)
响应的HTTP协议版本为1.0 ,默认不开启keep-alive
![](https://img.haomeiwen.com/i19069836/2c3e2968250c6d87.png)
# 增加 Connection=keep-alive
res.headers['Connection'] = 'keep-alive'
重启flask服务,再次抓包。可以看到 TCP Keep-Alive网络包
![](https://img.haomeiwen.com/i19069836/0df227b391a013a8.png)
response header, keep-alive
![](https://img.haomeiwen.com/i19069836/95820cc306bddcc8.png)
此时http请求完成后,并未关闭TCP,再次用postman请求会发现并未出现握手。
![](https://img.haomeiwen.com/i19069836/61c0b888ef75ca03.png)
这个http长连接笔者等待了10分钟也还是keep-alive的状态...emmmm
当然,关闭postman或者后端服务后肯定断开了。
笔者重新安装了一个flask最新版测试
flask==2.1.3 再次测试
# Flask==2.1.3
# Werkzeug==2.1.2
from flask import Flask, make_response
app = Flask(__name__)
@app.route('/hello', methods=['get', 'post'])
def hello():
res = make_response('hello world')
return res
if '__main__' == __name__:
app.debug = True
app.run(host='0.0.0.0', port=5000)
同样用postman发送请求,发现握手与挥手的报文
![](https://img.haomeiwen.com/i19069836/87075323414dfa8f.png)
response header中connection为 close
![](https://img.haomeiwen.com/i19069836/71ce1540dbb8c8d9.png)
# 代码中加入Connection
res.headers['Connection'] = 'keep-alive'
postman测试,发现tcp还是挥手了。
![](https://img.haomeiwen.com/i19069836/a6364037cc39d9a2.png)
response header中居然有两个connection!
![](https://img.haomeiwen.com/i19069836/3286fb3b5e6a9a53.png)
![](https://img.haomeiwen.com/i19069836/ca130fdb8c58306b.png)
笔者以为是没设置对,尝试了其他方式仍然不得行!后发现是WerkZeug里面就是设置的 close
#res.headers['Connection'] = 'keep-alive'
#res.headers.setdefault('Connection', 'keep-alive')
#res.headers.set('Connection', 'keep-alive')
WerkZeug包里面的serving文件
![](https://img.haomeiwen.com/i19069836/0e3ea2db0cfd7c6e.png)
直接把源码改为Keep-Alive,果然就不会断开TCP了。
笔者查看了WerkZeug的更新记录,找到了日志说明。
![](https://img.haomeiwen.com/i19069836/4d84337b869c8e91.png)
![](https://img.haomeiwen.com/i19069836/090c87176fe0f6d2.png)
由于WerkZeug使用的http服务是http.server这个python内置的http服务器,这里面的代码对http请求处理上存在问题导致的。
笔者终于找到原因了。(●ˇ∀ˇ●)
当然生产环境我们使用的WSGI HttpServer一般都会选择gunicorn或者uwsgi。不会使用WerkZeug。
网友评论