WebSocket +Django 搭建
WebSocket
- WebSocket本质上是基于TCP协议。使用http握手建立通信的阶段,使用WebSocket保持实时通信。
- 与http半双工不同的是,WebSocket是正在实现全双工通信的协议。
在html5实例化一个WebSocket对象
var Socket = new WebSocket(url, [protocol] );WebSocket属性
- Socket.readyState:只读属性,表示连接状态 
  - 0-表示连接尚未建立
- 1-表示连接已经建立
- 2-表示连接正在关闭 
- 3-表示连接已经关闭或连接不能打开
 
- Socket.bufferedAmount:只读属性 
  -  表示已被send()放入正在队列中等待传输,但是还没有发出utf-8文本字节数 
 
-  
WebSocket事件
在前端写的函数
| 事件 | 事件处理程序 | 描述 | 
|---|---|---|
| open | Socket.onopen | 连接建立时触发 | 
| message | Socket.onmessage | 客户端接收服务端数据时触发 | 
| error | Socket.onerror | 通信发生错误时触发 | 
| close | Socket.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!"); } } </script>
运行按键事件触发设置代码
<div id="sse">
         <a href="javascript:WebSocketTest()">运行 WebSocket</a>
      </div>
python WebSocket获取实时数据几种常见连接方式
-  使用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 WebSocketClientclass 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 websocketdef 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><script type="text/javascript"> 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!"); } } </script></head>
<body><div id="sse"> <a href="javascript:WebSocketTest()">运行 WebSocket</a> </div>
</body>
</html>
channels还有其他类型
Websocket.connect 建立连接
Websocket.disconnet 断开连接组Group:channels给咱们定义个group概念。也就是说只要consumer和这个组建立的关系,其他的各个consumer都会接受到消息
consumer.py
# In consumers.py from channels import GroupConnected 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();
 
                    
                     
                    
                 
                    
                 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号