學(xué)習(xí)筆記20170601">【PMP】學(xué)習(xí)筆記20170601
1065
2022-05-30
WebSocket協(xié)議
用這個(gè)協(xié)議最方便的就是,服務(wù)器主動(dòng)向客戶端推送信息。客戶端也可以主動(dòng)向服務(wù)器發(fā)送信息。屬于應(yīng)用層協(xié)議,在握手階段還是使用了HTTP的協(xié)議。
在普通的連接過程中,HTTP通過Request請(qǐng)求來界定,一個(gè)Request得到一個(gè)Response,在HTTP1.0中,這次HTTP請(qǐng)求就已經(jīng)結(jié)束了。
在 HTTP1.1 中進(jìn)行了改進(jìn),使得有一個(gè) keep-alive,也就是說,在一個(gè) HTTP 連接中,可以發(fā)送多個(gè) Request,接收多個(gè) Response。但是請(qǐng)記住 Request = Response, 在 HTTP 中永遠(yuǎn)是這樣,也就是說一個(gè) Request 只能有一個(gè) Response。而且這個(gè) Response 也是被動(dòng)的,不能主動(dòng)發(fā)起。
可以看到這兩種方式都體現(xiàn)出了HTTP協(xié)議的被動(dòng)性,也就是說服務(wù)端不能主動(dòng)聯(lián)系客戶端,只能有客戶端發(fā)起。而Websocket就解決了這個(gè)問題,當(dāng)服務(wù)器完成協(xié)議升級(jí)后(HTTP->Websocket),服務(wù)端就可以主動(dòng)推送信息給客戶端了。
1、安裝Websocket
通過命令:
pip install flask-socketio pip install websocket-gevent
1
2
(第二條這條命令部分機(jī)子是需要的,有些環(huán)境不需要,具體原因不大清楚,筆者在進(jìn)行項(xiàng)目時(shí)需要安裝這兩個(gè),按道理第一個(gè)就夠了。)
安裝flask_socketio模塊實(shí)現(xiàn)了Flask對(duì)websocket的封裝,從而允許建立在flask上的應(yīng)用的服務(wù)端和客戶端建立全雙工通信。
2、啟動(dòng)socketio的方式
原flask下是通過 app.run啟動(dòng)的,現(xiàn)在需要進(jìn)一步封裝flask。通過如下代碼進(jìn)行啟動(dòng)項(xiàng)目:
socketio.run(app, debug=True,host='127.0.0.1',port=5000)
1
3、服務(wù)端推送消息函數(shù)
send函數(shù)
send函數(shù)用于推送無名事件,代碼如下:
@socketio.on('connect',namespace='/test_conn') def handle_message(message): send(data=message, namespace='/test_conn')
1
2
3
emit函數(shù)
@socketio.on('connect',namespace='/test_conn') def handle_my_custom_event(json): emit('my response', data=json, namespace='/test_conn')
1
2
3
在上面的函數(shù)中,@socketio.on(‘connect’, namespace=’/test_conn’)中的connect是socketio的內(nèi)置事件。
當(dāng)客戶端和服務(wù)端連接之后,前端和后端都會(huì)收到一個(gè)名為connet的事件,服務(wù)端接收到這個(gè)事件之后就會(huì)執(zhí)行def函數(shù)里面的內(nèi)容,然后就可以使用emit或者send函數(shù)推送消息給前端了。
namespace可以標(biāo)志多個(gè)事件,官方文檔的解釋是:“當(dāng)一個(gè)客戶端連接服務(wù)器的不同命名域的時(shí)候,可以在同一個(gè)socket連接里完成”。
一個(gè)namespace定義了一個(gè)后端的websocket連接接口,客戶端和服務(wù)器通過三次握手建立socket連接后,連接不同的服務(wù)器接口,socket連接并不會(huì)斷開。而一個(gè)后端接口可以接受多個(gè)客戶端的socket連接,如果在后端的emit中定義‘broadcast=True’,那么所有連接到這個(gè)命名域的客戶端都會(huì)收到這個(gè)消息。不同命名域之間可以通過發(fā)送消息指定命名域的方式來相互通信。
emit函數(shù)中,第一個(gè)參數(shù)’server_response’是服務(wù)端發(fā)送這個(gè)消息的事件名,在客戶端要建立一個(gè)接受這個(gè)事件的函數(shù)處理,后面的字典就是消息內(nèi)容,namespace=’/test_conn’表示這個(gè)消息發(fā)送到信道(test_conn)中。
4、使用線程來進(jìn)行while循環(huán)推送消息
在理論上需要定時(shí)推送消息的時(shí)候,大部分是使用while循環(huán)實(shí)現(xiàn)的,但是實(shí)際上這樣容易影響服務(wù)端死循環(huán),導(dǎo)致連接出現(xiàn)錯(cuò)誤,代碼如下:
正確的代碼應(yīng)該是建立一個(gè)后端線程,通過后臺(tái)線程執(zhí)行while的循環(huán)從而解決該問題。
5、客戶端代碼
function onload() { $(document).ready(function() { namespace='/test_conn' var socket = io.connect('ws://127.0.0.1:11000/test_conn'); //或者使用 var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + namespace); socket.on('server_response', function(res) { var msg = res.data; console.log(msg); }); }); 使用io.connect建立指定namespace的socket連接了,使用socket.on監(jiān)聽并捕捉服務(wù)端發(fā)來的消息,并操作前端界面進(jìn)行相應(yīng)改變。 }
1
2
3
4
5
6
7
8
9
10
11
12
13
Flask websocket
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。