WebSocket +Django 搭建

个人博客,欢迎来撩 fangzengye.com

WebSocket

  1. WebSocket本质上是基于TCP协议。使用http握手建立通信的阶段,使用WebSocket保持实时通信。
  2. 与http半双工不同的是,WebSocket是正在实现全双工通信的协议。

 

在html5实例化一个WebSocket对象

var Socket = new WebSocket(url, [protocol] );

WebSocket属性

  • Socket.readyState:只读属性,表示连接状态
    • 0-表示连接尚未建立
    • 1-表示连接已经建立
    • 2-表示连接正在关闭

       

    • 3-表示连接已经关闭或连接不能打开
  • Socket.bufferedAmount:只读属性
    • 表示已被send()放入正在队列中等待传输,但是还没有发出utf-8文本字节数

WebSocket事件

在前端写的函数

事件事件处理程序描述
openSocket.onopen连接建立时触发
messageSocket.onmessage客户端接收服务端数据时触发
errorSocket.onerror通信发生错误时触发
closeSocket.onclose连接关闭时触发

客户端Html和javascript代码实现

<script type="text/javascript">
         function WebSocketTest()
         {
            if ("WebSocket" in window)
            {
               alert("您的浏览器支持 WebSocket!");
           // 打开一个 web socket
           var ws = new WebSocket("ws://localhost:9998/echo");

                
ws.onopen = function() // 建立连接
{
// Web Socket 已连接上,使用 send() 方法发送数据
ws.send("发送数据");
alert("数据发送中...");
};
                
ws.onmessage = function (evt) // 保持通信
{
var received_msg = evt.data;
alert("数据已接收...");
};
                
ws.onclose = function()// 关闭通信
{
// 关闭 websocket
alert("连接已关闭...");
};
}

        else
        {
           // 浏览器不支持 WebSocket
           alert("您的浏览器不支持 WebSocket!");
        }
     }
  &lt;/script&gt;

 

运行按键事件触发设置代码

 

<div id="sse">
         <a href="javascript:WebSocketTest()">运行 WebSocket</a>
      </div>

 

python WebSocket获取实时数据几种常见连接方式

  1. 使用create_connection链接

需要pip install websocket-client (此方法不建议使用,链接不稳定,容易断,并且连接很耗时)

import time
from websocket import create_connection

url = 'wss://i.cg.net/wi/ws'
while True: # 一直链接,直到连接上就退出循环
time.sleep(2)
try:
ws = create_connection(url)
print(ws)
break
except Exception as e:
print('连接异常:', e)
continue
while True: # 连接上,退出第一个循环之后,此循环用于一直获取数据
ws.send('{"event":"subscribe", "channel":"btc_usdt.ticker"}')
response = ws.recv()
print(response)

2. 运行效果很不错

import json
from ws4py.client.threadedclient import WebSocketClient

class CG_Client(WebSocketClient):

def opened(self):
    req = '{"event":"subscribe", "channel":"eth_usdt.deep"}'
    self.send(req)

def closed(self, code, reason=None):
    print("Closed down:", code, reason)

def received_message(self, resp):
    resp = json.loads(str(resp))
    data = resp['data']
    if type(data) is dict:
        ask = data['asks'][0]
        print('Ask:', ask)
        bid = data['bids'][0]
        print('Bid:', bid)

if name == 'main':
ws = None
try:
ws = CG_Client('wss://i.cg.net/wi/ws')
ws.connect()
ws.run_forever()
except KeyboardInterrupt:
ws.close()

3.与第一种差不多

import websocket

while True:
ws = websocket.WebSocket()
try:
ws.connect("wss://i.cg.net/wi/ws")
print(ws)
break
except Exception as e:
print('异常:', e)
continue
print('OK')
while True:
req = '{"event":"subscribe", "channel":"btc_usdt.deep"}'
ws.send(req)
resp = ws.recv()
print(resp)

4.使用第三方库WebScocket(推荐使用)

PYPI地址 https://pypi.org/project/websocket_client/

import websocket

def on_message(ws, message): # 服务器有数据更新时,主动推送过来的数据
print(message)

def on_error(ws, error): # 程序报错时,就会触发on_error事件
print(error)

def on_close(ws):
print("Connection closed ……")

def on_open(ws): # 连接到服务器之后就会触发on_open事件,这里用于send数据
req = '{"event":"subscribe", "channel":"btc_usdt.deep"}'
print(req)
ws.send(req)

if name == "main":
websocket.enableTrace(True)
ws = websocket.WebSocketApp("wss://i.cg.net/wi/ws",
on_message=on_message,
on_error=on_error,
on_close=on_close)
ws.on_open = on_open
ws.run_forever(ping_timeout=30)

高级一点
import socket
from websocket import create_connection, WebSocket
class MyWebSocket(WebSocket):
    def recv_frame(self):
        frame = super().recv_frame()
        print('yay! I got this frame: ', frame)
        return frame

ws = create_connection("ws://echo.websocket.org/",
                        sockopt=((socket.IPPROTO_TCP, socket.TCP_NODELAY, 1),), class_=MyWebSocket)

Django 实现WebSocket(假设您已建好Django的基础框架了)

官方文档 址:https://channels.readthedocs.io/en/stable/

1. 安装channels

pip install channels

2. 设置路由

在settings 加入我们的channels进入INSTALL_APP

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    ...
    'channels',
)

3. channels:是先进先出的消息队列

4.看看框架是怎么样:

 

5.代码:

consumer.py

# In consumers.py

def ws_message(message):
# ASGI WebSocket packet-received and send-packet message types
# both have a "text" key for their textual data.
message.reply_channel.send({
"text": message.content['text'],
})

Routing.py

# In routing.py
from channels.routing import route
from myapp.consumers import ws_message

channel_routing = [
route("websocket.receive", ws_message),
]

前端htmldaima

<!DOCTYPE HTML>
<html>
   <head>
   <meta charset="utf-8">
   <title>测试websocket</title>
  &lt;script type="text/javascript"&gt;
     function WebSocketTest()
     {
        if ("WebSocket" in window)
        {
           alert("您的浏览器支持 WebSocket!");

           // 打开一个 web socket
            ws = new WebSocket("ws://localhost:8000/path/");

           ws.onopen = function()
           {
              // Web Socket 已连接上,使用 send() 方法发送数据
              ws.send("发送数据");
              alert("数据发送中...");
           };

           ws.onmessage = function (evt)
           {
              var received_msg = evt.data;
              alert("数据已接收...");
              alert("数据:"+received_msg)
           };

           ws.onclose = function()
           {
              // 关闭 websocket
              alert("连接已关闭...");
           };
        }

        else
        {
           // 浏览器不支持 WebSocket
           alert("您的浏览器不支持 WebSocket!");
        }
     }
  &lt;/script&gt;

</head>
<body>

  &lt;div id="sse"&gt;
     &lt;a href="javascript:WebSocketTest()"&gt;运行 WebSocket&lt;/a&gt;
  &lt;/div&gt;

</body>
</html>

 

channels还有其他类型

Websocket.connect 建立连接
Websocket.disconnet 断开连接

组Group:channels给咱们定义个group概念。也就是说只要consumer和这个组建立的关系,其他的各个consumer都会接受到消息

consumer.py

# In consumers.py
from channels import Group

Connected to websocket.connect

def ws_add(message):
message.reply_channel.send({"accept": True})
Group("chat").add(message.reply_channel)

Connected to websocket.receive

def ws_message(message):
Group("chat").send({
"text": "[user] %s" % message.content['text'],
})

Connected to websocket.disconnect

def ws_disconnect(message):
Group("chat").discard(message.reply_channel)

routing.py

from channels.routing import route
from myapp.consumers import ws_add, ws_message, ws_disconnect

channel_routing = [
route("websocket.connect", ws_add),
route("websocket.receive", ws_message),
route("websocket.disconnect", ws_disconnect),
]

前端html代码

// Note that the path doesn't matter right now; any WebSocket
// connection gets bumped over to WebSocket consumers
socket = new WebSocket("ws://" + window.location.host + "/chat/");
socket.onmessage = function(e) {
    alert(e.data);
}
socket.onopen = function() {
    socket.send("hello world");
}
// Call onopen directly if socket is already open
if (socket.readyState == WebSocket.OPEN) socket.onopen();

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2020-12-11 16:38  开源的Boy  阅读(330)  评论(0)    收藏  举报