原文轉載自「劉悅的技術博客」https://v3u.cn/a_id_158
在之前的一篇文章中:爲美多商城(Django2.0.4)添加基於websocket的實時通信,主動推送,聊天室及客服系統,詳細介紹了websocket協議以及結合Django如何實現各種功能,本次我們嘗試採用Socket.io這個庫和Flask來配合使用,完成一個簡易的在線客服聊天系統,看看二者有什麼區別。
Socket.IO 就是一個封裝了 Websocket、基於 Node 的 JavaScript 框架,包含 client 的 JavaScript 和 server 的 Node(現在也支持python,go lang等語言)。其屏蔽了所有底層細節,讓頂層調用非常簡單,另外,Socket.IO 還有一個非常重要的好處。其不僅支持 WebSocket,還支持許多種輪詢機制以及其他實時通信方式,並封裝了通用的接口。這些方式包含 Adobe Flash Socket、Ajax 長輪詢、Ajax multipart streaming 、持久 Iframe、JSONP 輪詢等。換句話說,當 Socket.IO 檢測到當前環境不支持 WebSocket 時,能夠自動地選擇最佳的方式來實現網絡的實時通信,這一點就比websocket要智能不少。
我們先進行後端服務的搭建
pip install flask
pip install flask-cors
pip install flask-socketio
分別安裝Flask本地,跨域模塊,以及socketio模塊
適當升級你的pip,注意版本不要過低,下面是本次demo的版本號
Flask 1.1.1
Flask-Cors 3.0.8
Flask-SocketIO 4.3.0
Flask-SQLAlchemy 2.4.1
隨後我們簡單寫一個flask的入口啓動文件 manage.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import pymysql
from flask import request,jsonify
from flask_cors import CORS
from flask_socketio import SocketIO,send,emit
import urllib.parse
pymysql.install_as_MySQLdb()
app = Flask(__name__)
CORS(app,cors_allowed_origins="*")
socketio = SocketIO(app,cors_allowed_origins='*')
@socketio.on('message')
def handle_message(message):
message = urllib.parse.unquote(message)
print(message)
send(message,broadcast=True)
@socketio.on('connect', namespace='/chat')
def test_connect():
emit('my response', {'data': 'Connected'})
@socketio.on('disconnect', namespace='/chat')
def test_disconnect():
print('Client disconnected')
if __name__ == '__main__':
socketio.run(app,debug=True,host="0.0.0.0",port=5000)
這裏簡單說一下需要注意的地方,實例化socketio對象的時候,要加上cors_allowed_origins來設置跨域,前後端分離項目讓人傷腦筋的地方就是瀏覽器同源策略問題,而跨域最好由server端來單獨配置,這樣的好處是當多個前端項目同時共用一套微服務接口時,就不用每個前端項目都配置一次跨域了。
我們寫了三個基於socketio的視圖方法,connect和disconnect顧名思義,當clinet發起連接或者斷開時我們可以及時捕獲到,而message方法就是前後端進行消息通信的重要方法。
發送消息的時候方法加了一個broadcast參數,這是socket.io極具特色的功能,類似廣播的效果,可以同時給不同鏈接的client發送消息,即可以用於聊天,也可以用來做消息推送。
最後需要注意的一點是,client發送消息時,最好用urlencode編碼一下,這樣可以解決中文亂碼問題,而在server端,可以用urllib.parse.unquote()來進行解碼操作。
運行命令啓動後端服務
python3 manage.py
服務正常啓動在5000端口上,就說明後端沒有問題了。
隨後我們來配置前端(client),前端採用vue2.0框架來驅動,也需要安裝socket.io模塊
npm install [email protected]
這裏一定要指定版本號來安裝,版本是2.1.0,因爲該依賴的最新版在vue2.0項目中編譯時會報錯
在入口文件main.js中引用
import VueSocketio from 'vue-socket.io';
Vue.use(VueSocketio,'http://127.0.0.1:5000');
注意鏈接的url是後端服務的地址+端口,千萬不要加其他url後綴或者命名空間
新建一個index.vue組件來進行模擬用戶鏈接
<template>
<div>
<div v-for="item in log_list"
>
{{item}}
</div>
<input v-model="msg" />
<button @click="send">發送消息</button>
</div>
</template>
<script>
export default {
data () {
return {
msg: "",
log_list:[]
}
},
//註冊組件標籤
components:{
},
sockets:{
connect: function(){
console.log('socket 連接成功')
},
message: function(val){
console.log('返回:'+val);
this.log_list.push(val);
}
},
mounted:function(){
},
methods:{
send(){
this.$socket.emit('message',encodeURI("用戶:"+this.msg));
},
}
}
</script>
<style>
</style>
啓動前端服務
npm run dev
訪問前端頁面 http://localhost:8080 可以看到服務成功鏈接
這時可以嘗試再做一個後臺客服的組件頁面item.vue,模擬用戶和客服分別在不同的電腦進行聊天的場景
<template>
<div>
<div v-for="item in log_list"
>
{{item}}
</div>
<input v-model="msg" />
<button @click="send">發送消息</button>
</div>
</template>
<script>
export default {
data () {
return {
msg: "",
log_list:[]
}
},
//註冊組件標籤
components:{
},
sockets:{
connect: function(){
console.log('socket 連接成功')
},
message: function(val){
console.log('返回:'+val);
this.log_list.push(val);
}
},
mounted:function(){
},
methods:{
send(){
this.$socket.emit('message',encodeURI("客服:"+this.msg));
},
}
}
</script>
<style>
</style>
效果是這樣的:
整個流程還是相對簡單的,比起django的dwebsocket模塊,socket.io顯然更加靈活和方便,如果需要做一些主動推送任務,也可以利用socket.io的廣播功能,其原理和實時聊天是一樣的。
原文轉載自「劉悅的技術博客」 https://v3u.cn/a_id_158