Python Falcon 简明教程
Python Falcon - Websocket
WebSocket 是客户端与服务器之间的持久连接,可在这两者之间提供双向 full-duplex 通信。通信经由 HTTP 在单个 TCP/IP 套接字连接中发生。这可以看做是 HTTP 的升级,而不是一个协议本身。
HTTP 的局限性之一是它是一个严格的半双工或单向协议。另一方面,借助 WebSocket,我们可以发送基于消息的数据(类似于 UDP),但借助 TCP 的可靠性。WebSocket 使用 HTTP 作为初始传输机制,但在收到 HTTP 响应后保持 TCP 连接的活动状态。可以将同一连接对象用于客户端和服务器之间的双向通信。因此,可以使用 WebSocket API 构建实时应用。
Falcon 的 Websocket 支持仅适用于 ASGI 应用。若要提供 Websocket 能力,资源类应具有 on_websocket() 回应器协程。
async def on_websocket(self, req, ws):
. . .
Websocket 请求还可由钩子和中间件拦截。将传递 falcon.asgi.WebSocket 对象,而不是 Response 对象。
How Does a WebSocket Function in Falcon?
以下示例演示了 Falcon 应用中 WebSocket 的功能。首先,我们有一个 on_get() 回应器,它用来呈现一个模板。
Example
客户端浏览器显示一个带有文本字段和按钮的表单,单击该按钮时,就会创建一个 websocket 对象,并触发 on_websocket() 回应器。它接受用户输入的消息,并以“消息文本为”为前缀将它反馈给客户端。
import falcon
import falcon.asgi
import jinja2
html = """
<!DOCTYPE html>
<html>
<head>
<title>Chat</title>
</head>
<body>
<script>
var ws = new WebSocket("ws://localhost:8000/hello");
ws.onmessage = function(event) {
var messages =document.getElementById('messages')
var message = document.createElement('li')
var content = document.createTextNode(event.data)
message.appendChild(content)
messages.appendChild(message)
};
function sendMessage(event) {
var input = document.getElementById("messageText")
ws.send(input.value)
input.value = ''
event.preventDefault()
}
</script>
<h1>WebSocket Chat</h1>
<form action="" onsubmit="sendMessage(event)">
<input type="text" id="messageText" autocomplete="off"/>
<button>Send</button>
</form>
<ul id='messages'></ul>
</body>
</html>
"""
class HelloResource:
async def on_get(self, req, resp):
"""Handles GET requests"""
resp.status = falcon.HTTP_200
resp.content_type = 'text/html'
template=jinja2.Template(html)
resp.body=template.render()
async def on_websocket(self, req, websocket):
await websocket.accept()
while True:
data = await websocket.receive_text()
await websocket.send_text(f"Message text was: {data}")
app = falcon.asgi.App()
hello = HelloResource()
app.add_route('/hello', hello)
import uvicorn
if __name__ == "__main__":
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)