django进阶02websocket

技术_编程语言 专栏收录该内容
128 篇文章 0 订阅

原创博文地址:django进阶02websocket

本文适合有一定websocket基础的,至少完整看过前后端demo的读者,一窍不通的小白建议先阅读“参考”部分的博文扫扫盲。
基于django的dwebsocket组件(目前虽然不在维护,但正常使用没问题)

前端方法

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script type="text/javascript">
    var socket = new WebSocket("ws:" + window.location.host + "/drug/drug_connect/");
    socket.onopen = function () {
        console.log('WebSocket open');//成功连接上Websocket
        socket.send('adasdasda。。。。');//发送数据到服务端
    };
    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();
</sctipt>

由于js的异步友好性,所以代码看起来非常清爽,也容易理解。socket连接,成功后干什么(onopen),收到消息后干嘛(onmessage),如何关闭等。而且也会自动发送Pingpong包确保连接的保持。

后端方法

dwebsocket的一些内置方法:
request.is_websocket():判断请求是否是websocket方式,是返回true,否则返回false
request.websocket: 当请求为websocket的时候,会在request中增加一个websocket属性,
WebSocket.wait() 返回客户端发送的一条消息,没有收到消息则会导致阻塞
WebSocket.read() 和wait一样可以接受返回的消息,只是这种是非阻塞的,没有消息返回None
WebSocket.count_messages()返回消息的数量
WebSocket.has_messages()返回是否有新的消息过来
WebSocket.send(message)像客户端发送消息,message为byte类型

后端方法相对前端就没有那么友好了。如果面对一个特定需求如何实现呢?

场景1,1v0聊天

这个实际业务中没啥用,仅用来验证websocket接口性质,了解接口特性而已。

 

1
2
3
4
5
6
7
8
9
10
@accept_websocket
def start_server_script(request):
    if request.is_websocket():
        # "这里实现wbsocket连接逻辑"
        for info in request.websocket:# 这里需要注意的是,这个for后面的对象,request.websocket是阻塞的,也就是说如果对方发送消息,info=新消息,循环走一圈,如果对方不发消息,for这里会“卡住”,这里容易忽略
            request.websocket.send("你刚才对我说:%s"%info)
         print('这里其实不会被执行')
    else:
        # "这里实现http连接逻辑"
        pass

场景2,多v多聊天

上面的例子很简单吧,自己和自己聊天,多v多聊天代码和上面差不多!
将request.websocket看做普通对象,将所所有连接的websocket保存全局变量中,依次send(msg)即可.

 

1
2
3
4
5
6
7
8
9
10
11
12
wobsocket_map=dict()
@accept_websocket
def start_server_script(request):
    if request.is_websocket():
        wobsocket_map[id(request.websocket)]=request.websocket
        # "这里实现wbsocket连接逻辑"
        for info in request.websocket:# 这里需要注意的是,这个for后面的对象,request.websocket是阻塞的,也就是说如果对方发送消息,info=新消息,循环走一圈,如果对方不发消息,for这里会“卡住”,这里容易忽略
            [websocket.send("你刚才对我说:%s"%info) for websocket in wobsocket_map.values()]
         print('这里其实不会被执行')
    else:
        # "这里实现http连接逻辑"
        pass

可以实现效果,将msg发送给所有连接到此websocket的对象!

场景3,视频播放

视频播放是一种类似死循环的处理逻辑

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 伪代码,不保证能跑,意思差不多
# 其他函数通过next(),or .send()调用此生成器,不断生成各个视频帧的base64编码(看不懂的话,百度"yield")
url='rtmp://xxxx'
@accept_websocket
def show_video(request):
    video=video_img_base64(url)
    base64=next(video)
    while base64 is not None: # 这个就是类似死循环的东西(当然这个并非真正死循环,但很多情况退出只能放到循环里break,这里只能采用while True)
        request.websocket.send({'img_base64':base64})
        base64=video.send(None)

def video_img_base64(url):
    cap=cv2.VideoCapture(url)
    ret,frame=cap.read()
    while ret:
        yield base64(frame.tobytes()).decode('utf8')
        ret,frame=cap.read()
    else:
        yield None #调用方一旦收到None,避免调用next() or send()否则抛出异常,需要做异常处理

场景4,视频播放及控制

相比前面的例子,多了控制逻辑,那么问题来了,控制逻辑放哪里?
如果后台也可以向js那样,onmessage(xxx),这样就简单多了,onmessage(),根据message修改一个类似全局变量的东西就行。但是并没有。
从场景1的例子可以看出,websocket非常擅长处理request-response的情况。例子3,看到其也可以处理 持续response推送的情况,那么如何实现类似异步里面交互式响应呢?
这里提供一个简单模板

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
send_queue=Queue()
@accept_websocket
def websocket_ctrl(request):
    if request.is_websocket:
        while True:# 由于使用同步方式处理异步,所以这里必然死循环
            if request.websocket.count_messages()>0:
                message=request.websocket.read()
                while message:
                    onmessage(message)
                    message=request.websocket.read()
            if not send_queue.empty:# 需向send_queue放东西,send函数中会放message
                messsage=send_queue.pop()
                while message:
                    message=request.websocket.send(message)
                    messsage=send_queue.pop()

def onmessage(message):
    pass # 这里可以放你想在收到消息时做的事情,类似异步方法的onmessage,如果需要反馈修改,比如改变上一级的执行逻辑,则可以通过返回值的方式,传递给上一级调用者,让上一级调用者通过返回值调整自身执行逻辑

# 他人调用这个方法,将消息加入发送队列,在websocket_ctrl的循环中会取得,并发出
def send(message):
   send_queue.put(message)

注意:尽可能避免使用

 

1
2
for message in request.websocket:
    print(message)

由于其会导致阻塞,特别强调这一点,因为大多数情况,我们看到for循环,会想当然以为”它很快会结束“,其实未必。
还有一点就是需要加异常处理,对方可能主动关闭连接,此时后台如果发送消息,会抛出异常。

总结

流程图

方法典型使用形态阻塞开启连接(客户端)发送消息(客户端)断开连接
request.websocketfor msg in request.websocket:func(msg)halt:request.websocketmsg<=’common msg’msg<=None
request.websocket.wait()while True: msg=request.websocket.wait()halt:request.websocket.wait()msg<=’common msg’msg<=None
request.websocket.read()while True:msg=request.websocket.read()loop:msg<=request.websocket.read()msg<=request.websocket.read()except
request.websocket.has_messages()while True:has_msg=request.websocket.has_messages();if has_msg:msg=request.websocket.read()loop:has_msg<=request.websocket.has_messages()msg<=request.websocket.read()has_msg=True and msg=None
request.websocket.count_messages()while True:count=request.websocket.count_messages();if count>0:msg=request.websocket.read()loop:count<=request.websocket.count_messages()msg<=request.websocket.read()count>0 and msg=None

多重捕获会怎样?直观理解即可,只能有一个捕获到消息,不会重复捕获。

参考

https://www.520pf.cn/article/135.html
https://blog.csdn.net/xianailili/article/details/82180114

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
程序员的必经之路! 【限时优惠】 现在下单,还享四重好礼: 1、教学课件免费下载 2、课程案例代码免费下载 3、专属VIP学员群免费答疑 4、下单还送800元编程大礼包 【超实用课程内容】  根据《2019-2020年中国开发者调查报告》显示,超83%的开发者都在使用MySQL数据库。使用量大同时,掌握MySQL早已是运维、DBA的必备技能,甚至部分IT开发岗位也要求对数据库使用和原理有深入的了解和掌握。 学习编程,你可能会犹豫选择 C++ 还是 Java;入门数据科学,你可能会纠结于选择 Python 还是 R;但无论如何, MySQL 都是 IT 从业人员不可或缺的技能!   套餐中一共包含2门MySQL数据库必学的核心课程(共98课时)   课程1:《MySQL数据库从入门到实战应用》   课程2:《高性能MySQL实战课》   【哪些人适合学习这门课程?】  1)平时只接触了语言基础,并未学习任何数据库知识的人;  2)对MySQL掌握程度薄弱的人,课程可以让你更好发挥MySQL最佳性能; 3)想修炼更好的MySQL内功,工作中遇到高并发场景可以游刃有余; 4)被面试官打破沙锅问到底的问题问到怀疑人生的应聘者。 【课程主要讲哪些内容?】 课程一:《MySQL数据库从入门到实战应用》 主要从基础篇,SQL语言篇、MySQL进阶篇三个角度展开讲解,帮助大家更加高效的管理MySQL数据库。 课程二:《高性能MySQL实战课》主要从高可用篇、MySQL8.0新特性篇,性能优化篇,面试篇四个角度展开讲解,帮助大家发挥MySQL的最佳性能的优化方法,掌握如何处理海量业务数据和高并发请求 【你能收获到什么?】  1.基础再提高,针对MySQL核心知识点学透,用对; 2.能力再提高,日常工作中的代码换新貌,不怕问题; 3.面试再加分,巴不得面试官打破沙锅问到底,竞争力MAX。 【课程如何观看?】  1、登录CSDN学院 APP 在我的课程中进行学习; 2、移动端:CSDN 学院APP(注意不是CSDN APP哦)  本课程为录播课,课程永久有效观看时长 【资料开放】 课件、课程案例代码完全开放给你,你可以根据所学知识,自行修改、优化。  下载方式:电脑登录课程观看页面,点击右侧课件,可进行课程资料的打包下载。
©️2020 CSDN 皮肤主题: 程序猿惹谁了 设计师:白松林 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值