为美多商城(Django2.0.4)添加基于websocket的实时通信,主动推送,聊天室及客服系统

by Liu Yue/2019-04-17

websocket是个啥?

webSocket是一种在单个TCP连接上进行全双工通信的协议

webSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输

现在,很多网站为了实现推送技术,所用的技术都是轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。
而比较新的技术去做轮询的效果是Comet。这种技术虽然可以双向通信,但依然需要反复发出请求。而且在Comet中,普遍采用的长链接,也会消耗服务器资源。

在这种情况下,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯

轮询是几个意思?

轮询是最原始的实现实时Web应用的解决方案。轮询技术要求客户端以设定的时间间隔周期性地向服务端发送请求,频繁地查询是否有新的数据改动。明显地,这种方法会导致过多不必要的请求,浪费流量和服务器资源。总之就是一种low到爆炸的原始作坊水平的技术。

本文通过基于dwebsocket库来将socket嵌入到django服务中,使其服务兼具http协议和socket协议,能够达到实时前后端通信,后端主动推送等功能

安装dwebsocket库

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple dwebsocket

定义视图文件的逻辑views.py

#导入websocket装饰器
from dwebsocket.decorators import accept_websocket


#接收前端信息
@accept_websocket
def test_socket(request):
    if request.is_websocket():
        for message in request.websocket:
            c=str(message,encoding='utf-8')
            print(c)
            request.websocket.send(message)

#主动推送消息
@accept_websocket
def test_websocket(request):
    if request.is_websocket():
        while 1:
            time.sleep(1) ## 向前端发送时间
            dit = {
                'time':time.strftime('%Y.%m.%d %H:%M:%S',time.localtime(time.time()))
            }
            request.websocket.send(json.dumps(dit))

路由配置urls.py


#websocket
path('socket_test',TemplateView.as_view(template_name='md_admin/socket.html')),
path('websocket_test',TemplateView.as_view(template_name='md_admin/socket_push.html')),
path('test_socket',test_socket),
path('test_websocket',test_websocket),


定义前端发送消息的页面 socket.html


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Chat Room</title>
</head>
<body>
    <input id="chat-message-input" type="text" size="100"/><br/>
    <input id="chat-message-submit" type="button" value="Send" onclick='sendmessage()'/>
</body>
<script>
   
   //生成socket对象
   var socket = new WebSocket("ws:" + window.location.host + "/md_admin/test_socket");


            socket.onopen = function () {
                console.log('WebSocket open');//成功连接上Websocket
            };
            socket.onmessage = function (e) {
                console.log('message: ' + e.data);//打印服务端返回的数据
            };
            socket.onclose=function(e){
              console.log(e);
              socket.close(); //关闭TCP连接
            };
            if (socket.readyState == WebSocket.OPEN){
            socket.onopen();
            }

            window.s = socket;

function sendmessage(){

    window.s.send(document.getElementById("chat-message-input").value);

}

    
</script>
</html>

然后再定义一个页面,测试后台的主动推送socket_push.html


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Chat Room</title>
</head>
<body>
</body>
<script>
   
   //生成socket对象
   var socket = new WebSocket("ws:" + window.location.host + "/md_admin/test_websocket");


            socket.onopen = function () {
                console.log('WebSocket open');//成功连接上Websocket
            };
            socket.onmessage = function (e) {
                console.log('message: ' + e.data);//打印服务端返回的数据
            };
            socket.onclose=function(e){
              console.log(e);
              socket.close(); //关闭TCP连接
            };
            if (socket.readyState == WebSocket.OPEN){
            socket.onopen();
            }

   

    
</script>
</html>


可以看到,前后端无论是前端发送消息,还是后端主动推送消息,全部基于websocket,实现了真正意义上的实时通信,另外基于dwebsocket的聊天室可以在这里下载源码


https://gitee.com/QiHanXiBei/mei_do_mall/blob/master/dj_websocket.zip