WebSocket是啥?
WebSocket是HTML5引入的新的通信協議,主要由Web客戶端和服務器實現,當然它也可以在Web之外實現。
與HTTP連接不同,WebSocket連接是客戶端和服務器之間永久的雙向通信通道,其中任何一個都可以啓動交換。 一旦建立,連接一直有效,直到其中一方斷開連接。
flask實現websocket的兩種方式
flask 實現websocket有兩種方式實現,一種是flask_sockets方式,該方式是flask對websocket的最原始封裝,功能較爲單一,第二種方式Flask-SocketIO對websocket的封裝,該方式所能提供功能較多,不但實現了socket的基本通信功能,也可以結合flask相關接口,使其更加完備,因此網上對該api介紹也較多。
使用Flask-Sockets
服務端
服務端receive()方法,必須接收客戶端發送的數據,才能實現兩兩互相通信。
#!/usr/bin/env python
# encoding: utf-8
"""
@version: v1.0
@author: W_H_J
@license: Apache Licence
@contact: [email protected]
@software: PyCharm
@file: flaskWebSocket.py
@time: 2019/2/19 10:20
@describe: flask_sockets 實現websocket
"""
import json
import sys
import os
from flask_sockets import Sockets
import time
from gevent import monkey
from flask import Flask
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/' + '..'))
sys.path.append("..")
monkey.patch_all()
app = Flask(__name__)
sockets = Sockets(app)
now = time.strftime('%Y-%m-%d-%H-%M-%S', time.localtime(time.time()))
@sockets.route('/test') # 指定路由
def echo_socket(ws):
while not ws.closed:
ws.send(str("message test!")) # 回傳給clicent
""" 服務端必須接收到客戶端發的消息才能保持該服務運行,如果ws.receive()沒有接收到客戶端發送的
消息,那麼它會關閉與客戶端建立的鏈接
底層解釋:Read and return a message from the stream. If `None` is returned, then
the socket is considered closed/errored.
所以客戶端只建立連接,不與服務端交互通信,則無法實現自由通信狀態,之後在客戶端代碼處會有詳細內容。
"""
message = ws.receive() # 接收到消息
if message is not None:
print("%s receive msg==> " % now, str(json.dumps(message)))
""" 如果客戶端未發送消息給服務端,就調用接收消息方法,則會導致receive()接收消息爲空,關閉此次連接 """
ws.send(str(json.dumps(message))) # 回傳給clicent
else:
print(now, "no receive")
@app.route('/')
def hello():
return 'Hello World! server start!'
if __name__ == "__main__":
server = pywsgi.WSGIServer(('0.0.0.0', 5000), app, handler_class=WebSocketHandler)
print('server start')
server.serve_forever()
HTML客戶端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.2.0/jquery.js"></script>
</head>
<body>
<div id="time" style="width: 300px;height: 50px;background-color: #0C0C0C;
color: white;text-align: center;line-height: 50px;margin-left: 40%;font-size: 20px"></div>
<script>
var ws = new WebSocket("ws://127.0.0.1:5000/test"); #連接server--test
ws.onmessage = function (event) {
content = document.createTextNode(event.data); # 接收數據
$("#time").html(content);
};
</script>
</body>
</html>
python客戶端
#!/usr/bin/env python
# encoding: utf-8
"""
@version: v1.0
@author: W_H_J
@license: Apache Licence
@contact: [email protected]
@software: PyCharm
@file: flaskclicent.py
@time: 2019/2/19 10:34
@describe: flask_sockets 客戶端
"""
import sys
import os
import datetime
sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/' + '..'))
sys.path.append("..")
from websocket import create_connection
# websocket-client
# 通過socket路由訪問
now = datetime.datetime.now()
print(now)
def send_query_webSocket():
ws = create_connection("ws://10.10.20.21:9000/test")
result_1 = ws.recv() # 接收服務端發送的連接成功消息
print(result_1)
"""
上面recv()方法接收服務端 發送的第一條消息:ws.send(str("message test!")) # 回傳給clicent
下面再要接收消息,必須先給服務端發送一條消息,不然服務端message = ws.receive() 的receive方法
沒有收到消息,而這裏直接調用rece()方法去接收服務端消息,則會導致服務端關閉此次連接;
底層方法介紹:Read and return a message from the stream. If `None` is returned, then
the socket is considered closed/errored.
雖然此次連接關閉了,但是對於客戶端來說並不知情,而客戶端recv()方法又是一個阻塞方式運行,所以會導致
客戶端永遠阻塞在這裏無法關閉,這也是flask_sockets 客戶端服務端交互的一個缺點吧。
"""
ws.send("I am test msg!")
result = ws.recv()
print(result)
ws.close()
return True
if __name__ == '__main__':
send_query_webSocket()