后端Python3+Flask結(jié)合Socket.io配合前端Vue2.0實(shí)現(xiàn)簡(jiǎn)單全雙工在線客服系統(tǒng)

原文轉(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
image

服務(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ù)成功鏈接

image

這時(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>

效果是這樣的:

image

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

原文轉(zhuǎn)載自「劉悅的技術(shù)博客」 https://v3u.cn/a_id_158

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容