原文轉(zhuǎn)載自「劉悅的技術(shù)博客」https://v3u.cn/a_id_158
在之前的一篇文章中:為美多商城(Django2.0.4)添加基于websocket的實(shí)時(shí)通信,主動(dòng)推送,聊天室及客服系統(tǒng),詳細(xì)介紹了websocket協(xié)議以及結(jié)合Django如何實(shí)現(xiàn)各種功能,本次我們嘗試采用Socket.io這個(gè)庫(kù)和Flask來(lái)配合使用,完成一個(gè)簡(jiǎn)易的在線客服聊天系統(tǒng),看看二者有什么區(qū)別。
Socket.IO 就是一個(gè)封裝了 Websocket、基于 Node 的 JavaScript 框架,包含 client 的 JavaScript 和 server 的 Node(現(xiàn)在也支持python,go lang等語(yǔ)言)。其屏蔽了所有底層細(xì)節(jié),讓頂層調(diào)用非常簡(jiǎn)單,另外,Socket.IO 還有一個(gè)非常重要的好處。其不僅支持 WebSocket,還支持許多種輪詢機(jī)制以及其他實(shí)時(shí)通信方式,并封裝了通用的接口。這些方式包含 Adobe Flash Socket、Ajax 長(zhǎng)輪詢、Ajax multipart streaming 、持久 Iframe、JSONP 輪詢等。換句話說,當(dāng) Socket.IO 檢測(cè)到當(dāng)前環(huán)境不支持 WebSocket 時(shí),能夠自動(dòng)地選擇最佳的方式來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)的實(shí)時(shí)通信,這一點(diǎn)就比websocket要智能不少。
我們先進(jìn)行后端服務(wù)的搭建
pip install flask
pip install flask-cors
pip install flask-socketio
分別安裝Flask本地,跨域模塊,以及socketio模塊
適當(dāng)升級(jí)你的pip,注意版本不要過低,下面是本次demo的版本號(hào)
Flask 1.1.1
Flask-Cors 3.0.8
Flask-SocketIO 4.3.0
Flask-SQLAlchemy 2.4.1
隨后我們簡(jiǎn)單寫一個(gè)flask的入口啟動(dòng)文件 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)
這里簡(jiǎn)單說一下需要注意的地方,實(shí)例化socketio對(duì)象的時(shí)候,要加上cors_allowed_origins來(lái)設(shè)置跨域,前后端分離項(xiàng)目讓人傷腦筋的地方就是瀏覽器同源策略問題,而跨域最好由server端來(lái)單獨(dú)配置,這樣的好處是當(dāng)多個(gè)前端項(xiàng)目同時(shí)共用一套微服務(wù)接口時(shí),就不用每個(gè)前端項(xiàng)目都配置一次跨域了。
我們寫了三個(gè)基于socketio的視圖方法,connect和disconnect顧名思義,當(dāng)clinet發(fā)起連接或者斷開時(shí)我們可以及時(shí)捕獲到,而message方法就是前后端進(jìn)行消息通信的重要方法。
發(fā)送消息的時(shí)候方法加了一個(gè)broadcast參數(shù),這是socket.io極具特色的功能,類似廣播的效果,可以同時(shí)給不同鏈接的client發(fā)送消息,即可以用于聊天,也可以用來(lái)做消息推送。
最后需要注意的一點(diǎn)是,client發(fā)送消息時(shí),最好用urlencode編碼一下,這樣可以解決中文亂碼問題,而在server端,可以用urllib.parse.unquote()來(lái)進(jìn)行解碼操作。
運(yùn)行命令啟動(dòng)后端服務(wù)
python3 manage.py

服務(wù)正常啟動(dòng)在5000端口上,就說明后端沒有問題了。
隨后我們來(lái)配置前端(client),前端采用vue2.0框架來(lái)驅(qū)動(dòng),也需要安裝socket.io模塊
npm install vue-socket.io@2.1.0
這里一定要指定版本號(hào)來(lái)安裝,版本是2.1.0,因?yàn)樵撘蕾嚨淖钚掳嬖趘ue2.0項(xiàng)目中編譯時(shí)會(huì)報(bào)錯(cuò)
在入口文件main.js中引用
import VueSocketio from 'vue-socket.io';
Vue.use(VueSocketio,'http://127.0.0.1:5000');
注意鏈接的url是后端服務(wù)的地址+端口,千萬(wàn)不要加其他url后綴或者命名空間
新建一個(gè)index.vue組件來(lái)進(jìn)行模擬用戶鏈接
<template>
<div>
<div v-for="item in log_list"
>
{{item}}
</div>
<input v-model="msg" />
<button @click="send">發(fā)送消息</button>
</div>
</template>
<script>
export default {
data () {
return {
msg: "",
log_list:[]
}
},
//注冊(cè)組件標(biāo)簽
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>
啟動(dòng)前端服務(wù)
npm run dev
訪問前端頁(yè)面 http://localhost:8080 可以看到服務(wù)成功鏈接

這時(shí)可以嘗試再做一個(gè)后臺(tái)客服的組件頁(yè)面item.vue,模擬用戶和客服分別在不同的電腦進(jìn)行聊天的場(chǎng)景
<template>
<div>
<div v-for="item in log_list"
>
{{item}}
</div>
<input v-model="msg" />
<button @click="send">發(fā)送消息</button>
</div>
</template>
<script>
export default {
data () {
return {
msg: "",
log_list:[]
}
},
//注冊(cè)組件標(biāo)簽
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>
效果是這樣的:

整個(gè)流程還是相對(duì)簡(jiǎn)單的,比起django的dwebsocket模塊,socket.io顯然更加靈活和方便,如果需要做一些主動(dòng)推送任務(wù),也可以利用socket.io的廣播功能,其原理和實(shí)時(shí)聊天是一樣的。
原文轉(zhuǎn)載自「劉悅的技術(shù)博客」 https://v3u.cn/a_id_158