前面我们学习了异步web框架(sanic)和http异步调用库httpx,今天我们学习websocket技术。
websocket简介
我们知道HTTP协议是:请求->响应,如果没有响应就一直等着,直到超时;但是有时候后台的处理需要很长时间才能给到结果,比如30分钟,那HTTP的请求不可能等这么久,所以,可以通过 Ajax 轮询来解决。那就是每间隔一段时间就请求一次。
这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。
好了,WebSocket就是为了解决这个问题的,感兴趣去看其他资料!
智能聊天机器人
我一开始只是为了学习WebSocket找个例子,不少例子使用了聊天功能。我稍加改进就变成了智能聊天功能了。
通过异步sanic异步框架实现Web功能。官方文档里面给个WebSocket使用的例子。
https://sanic.readthedocs.io/en/latest/sanic/websocket.html
snaic部分核心代码如下:
import sanic
import httpx
from sanic import Sanic
from sanic.response import json
from sanic.websocket import WebSocketProtocol
from sanic.exceptions import NotFound
from sanic.response import html
from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('app', 'templates'))
app = Sanic(__name__)
@app.route('/')
async def index(request):
"""
聊天页面
"""
template = env.get_template('index.html')
html_content = template.render(title='聊天机器人')
return html(html_content)
@app.websocket('/chat')
async def chat(request, ws):
"""
处理聊天信息,并返回消息
"""
while True:
user_msg = await ws.recv()
print('Received: ' + user_msg)
intelligence_data = {"key": "free", "appid": 0, "msg": user_msg}
r = httpx.get("http://api.qingyunke.com/api.php", params=intelligence_data)
chat_msg = r.json()["content"]
print('Sending: ' + chat_msg)
await ws.send(chat_msg)
if __name__ == "__main__":
app.error_handler.add(
NotFound,
lambda r, e: sanic.response.empty(status=404)
)
app.run(host="192.168.0.7", port=8000, protocol=WebSocketProtocol, debug=True)
- index() 函数,返回聊天页面。这里用到了jinja2 模板渲染库。
- chat() 函数,通过webSocket实现消息的接收、处理和返回。
智能聊天是怎么做到的,这里要感谢 青云客网络,他们提供了免费的接口。(我当时也只是抱着试试看的态度,没想到,duang~! )
user_msg = "你好!"
intelligence_data = {"key": "free", "appid": 0, "msg": user_msg}
r = httpx.get("http://api.qingyunke.com/api.php", params=intelligence_data)
chat_msg = r.json()["content"]
print(chat_msg)
是不是超简单。
再来看前端代码,主要部分:
这里使用到了 bootstrap 前端框架,主要 调用部分在:
var Socket = new WebSocket(url, [protocol] );
- Socket.send(msg): 使用连接发送数据。
- Socket.onmessage: 客户端接收服务端数据时触发。
我知道,你迫不及待想要完整的代码了:
https://github.com/defnngj/learning-API-test