SRS源码分析-SDP内容解析

news2024/11/16 0:00:51

前言

在学习SRS的RTC模块之前,首先来分析下SRS在将rtmp推流转成rtc流,通过浏览器拉取webrtc流场景下产生的SDP内容

SDP格式介绍

SDP数据是文本格式,由多个 <key>=<value> 表达式构成,<key>的值只能是一个字符,<value>是一个字符串。注意:等号两边不能有空格

SDP主要由下列描述构成

  • 会话级描述(作用于整个会话),位置从 v= 行开始到第一个媒体描述为止
    • v=,sdp协议版本,默认为0
      • 例子:v=0
    • o=,发起者或者会话标识
      • 格式:o=<username> <session id> <version> <network type> <address type> <address>
      • 例子:o=SRS/4.0.245(Leo) 17778048 2 IN IP4 0.0.0.0
      • 说明:
        • username:用户名,不关心时,可用 ‘-’ 代替
        • session id: 会话id,会话唯一,规范建议使用NTP时间戳
        • version:会话版本,会话数据发生变化时该版本递增,规范建议使用NTP时间戳
        • network type:网络类型,IN表示 Internet
        • address type:地址类型,比如IP4、IP6等
        • address:域名或者IP地址
    • s=,会话名称,每个SDP里面只能有一个,且不能为空
      • 例子:s=SRSPlaySession
    • t=, 会话的有效时间
      • 格式:t=<start time> <stop time>
      • 例子:t=0 0
      • 说明:
        • start time/stop time均为NTP时间戳,均为0时,表示持久会话
    • b=,会话或媒体使用的建议带宽
  • 媒体级别描述(针对单个媒体流,一个会话中可以有多个媒体流),位置是从 m= 行开始到下一个媒体描述为止
    • m=, 媒体类型和传输地址
      • 格式:m=<media type> <port> <transport> <fmt list>
      • 例子:
        m=audio 9 UDP/TLS/RTP/SAVPF 111
        m=video 9 UDP/TLS/RTP/SAVPF 106
        
      • 说明:
        • media type:媒体类型,比如audio/video,application(bfcp)、text等类型
        • port:当前媒体类型的数据传输端口,在RTC场景下都是通过ICE candidate的信息来进行传输的,这个端口不会用到,但是在SIP场景下,这个port代表RTP端口,结合SDP会话级别描述中的C=中的ip地址,就可以知道在SIP中这路流的传输地址了
        • transport:传输协议,运行与c=中定义的地址类型之上,比如IP4,就是运行IP4之上的协议
        • fmt:代表音视频流的Media Codec,会话后面会跟着rtpmap、rtcp-fb、fmtp这些属性来进一步的描述,可以有多个值,存在多个值的时候,表示在这次会话中,多种类型都会用到,且第一个是默认的。
    • a=rtpmap,描述媒体会话描述(m=)中的fmt负载类型对应的编码器名称以及时钟速率信息和编码参数
      • 例子:
        a=rtpmap:111 opus/48000/2   // 对fmt为111的类型进行描述,audio codec/sample rate/channel
        a=rtpmap:106 H264/90000    // 对fmt为106的类型进行描述,video codec/timebase
        
    • a=fmtp,扩展字段,对媒体会话描述中的指定的fmt进行详细的参数格式指定(这个参数是需要有SDP传输,并且透传给使用此格式的媒体工具),每一个fmt只能有一个此描述
      • 格式:a=fmtp:<fmt> <format specific parameters>
      • 例子:a=fmtp:106 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
      • 说明:
        • fmt:媒体会话描述(m=)中指定的编码格式
        • format specific parameters:fmt对应的透传参数
        • level-asymmetry-allowed=1 => 是否允许两端的编码level不一致,必须SDP双方都为1
        • packetization-mode=1 => NALU打包方式,1表示,每帧图像被拆分到多个NALU单元传送,这些NALU单元传送的顺序是按照解码的顺序发送的
        • profile-level-id=42e01f => 指定H264的baseline和level等参数
    • a=extmap,扩展,支持什么协议
      • 例子:a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
    • a=sendrecv 媒体流的方向,既可以在会话描述中,也可以在媒体描述中
      • 例子: a=sendonly //仅发送
      • 说明:
        • sendrecv: 双向传输,即发送也接收
        • sendonly: 只发送数据
        • revonly: 只接收数据
        • inactive: 禁止发送数据
    • a=ssrc,RTC场景下音视频流和RTP/RTCP复用单一端口,通过SSRC区分每一路流,通过数据包的头部字段值来区分RTC/RTCP
      • 例子:
        a=ssrc:3459677730 cname:648fef7tl720yj49
        a=ssrc:3459677730 label:audio-8804l2a1
        a=ssrc:3459677731 cname:648fef7tl720yj49
        a=ssrc:3459677731 label:video-7h7733ci
        
      • 说明:cname是RTCP为每个RTP用户提供的一个全局唯一的规范名称标识符,描述该RTP流对应的RTCP协议中的cname。
      • label对应MediaStreamTrack ID
    • a=mid,当前媒体级别描述的ID,相当于给媒体级别描述编号
      • 例子:
        a=mid:audio   //audio就是当前这个媒体级别描述(m=)的ID
        a=mid:1   //同理,mid后面的值也可以是数字
        
  • 网络描述
    • c=,指明接收或者发送音视频使用的IP地址,webrtc使用ICE传输,这个被忽略
      • 格式:c=<nettype> <addrtype> <connection-address>
      • 例子:c=IN IP4 0.0.0.0
      • 说明:可以是会话级别或者是媒体级别,如果是媒体级别则每一个媒体级别描述都必须至少包含一个
    • a=candidate,candidate信息,传输的候选人,有host(主机)类型,有replay(反射)类型等
      • 格式:c=candidate:<foundation> <component-id> <transport> <priority> <conn-addr> <conn-port> <cand-type> <candidate-types>
      • 例子:
        // 传输协议是udp,优先级是2130706431
        // ip地址是124.221.111.76,端口8000,candidate的类型是host类型(即ip地址是主机的ip地址)
        // 候选者的代数式0,表示最初生成的
        a=candidate:0 1 udp 2130706431 124.221.111.76 8000 typ host generation 0
        
      • 说明:candidate信息可以有多个
  • 安全描述
    • a=crypto
    • a=ice-ufrag,ice short-term认证算法用到的用户名
    • a=ice-pwd, ice short-term认证算法用到的密码
    • a=fingerprint DTLS过程中的Certificate整数的签名
  • DTLS角色
    • a=setup
      • 例子:a=setup:passive
      • 说明:指定DTLS角色,Active:客户端,Passive:服务端,两者都可以则是actpass
  • ICE策略
    • a=ice-options:trickie
      • 说明:trickie说明SDP中没有包含candidate信息,candidate是通过信令单独交换的,client一边收集candidate,一边发送给对端进行连通性检查,提高连通性检查和候选捕获的速度
    • a=ice-lite
      • ICE的实现分为以下两种
        • Full ICE: 参与连接的两端都需要进行连通性检查
        • Lite ICE: 在Full ICE和Lite ICE连接时,只需要Full ICE一方进行连通性检查,Lite一方只需要回应Response消息就行。这种模式常用语公网设备
    • a=ice-option:renomination
      • 说明:允许 ICE controlling 一方动态重新提名新的 candidate ,默认情况 Offer 一方为controlling 角色,answer 一方为 controlled 角色;同时 Lite 一方只能为 controlled 角色
  • QOS,Grouping传输描述
    • a=rtcp-fb,支持的RTC反馈类型报文,媒体级别描述作用域
      • 例子:
        a=rtcp-fb:111 transport-cc   // 对于111这个fmt支持transport-cc这个报文
        a=rtcp-fb:106 transport-cc  // 同理
        a=rtcp-fb:106 nack              // 对于106这个fmt在ARQ上支持nack
        a=rtcp-fb:106 nack pli			// 对于106这个fmt在关键帧上支持pli处理
        
      • 注意:rtcp-fb不能用于会话级别描述,只能用于媒体级别描述,而且在m=描述的协议字段一定要有AVPF
    • a=group
      • 例子:a=group:BUNDLE 0 1
      • 说明:表示mid值为0和1的媒体会话描述(m=)进行复用端口传输
    • a=rtcp-mux
      • 说明:rtcp和rtp复用一个端口号

浏览器创建的本地Offer

通过SRS提供的RTC播放H5页面(http://localhost:8080/players/rtc_player.html?autostart=true)可以去拉取SRS上的RTC流(参考文章:SRS调试webrtc流),点击页面的播放视频,可以看到RTC播放页面请求了一个http接口,其中携带H5的local sdp。
播放页面请求的内容
local sdp的详细内容如下:

v=0
o=- 4052671107298259095 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0 1
a=extmap-allow-mixed
a=msid-semantic: WMS
m=audio 9 UDP/TLS/RTP/SAVPF 111 63 9 0 8 13 110 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:PTFm
a=ice-pwd:SjhcZkVwk0wlE9AAjAeFrv93
a=ice-options:trickle
a=fingerprint:sha-256 55:20:7B:84:80:3C:3A:95:17:C0:BE:0B:3C:23:DB:46:3A:58:29:87:1A:B1:E6:8C:53:9A:27:19:0C:BE:CF:86
a=setup:actpass
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=recvonly
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:63 red/48000/2
a=fmtp:63 111/111
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:126 telephone-event/8000
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 35 36 37 38 102 103 104 105 106 107 108 109 127 125 39 40 41 42 43 44 45 46 47 48 112 113 114 115 116 49
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:PTFm
a=ice-pwd:SjhcZkVwk0wlE9AAjAeFrv93
a=ice-options:trickle
a=fingerprint:sha-256 55:20:7B:84:80:3C:3A:95:17:C0:BE:0B:3C:23:DB:46:3A:58:29:87:1A:B1:E6:8C:53:9A:27:19:0C:BE:CF:86
a=setup:actpass
a=mid:1
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:13 urn:3gpp:video-orientation
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:5 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:10 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:11 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=recvonly
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 transport-cc
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96
a=rtpmap:98 VP9/90000
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 transport-cc
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=fmtp:98 profile-id=0
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=rtpmap:100 VP9/90000
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=fmtp:100 profile-id=2
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=rtpmap:35 VP9/90000
a=rtcp-fb:35 goog-remb
a=rtcp-fb:35 transport-cc
a=rtcp-fb:35 ccm fir
a=rtcp-fb:35 nack
a=rtcp-fb:35 nack pli
a=fmtp:35 profile-id=1
a=rtpmap:36 rtx/90000
a=fmtp:36 apt=35
a=rtpmap:37 VP9/90000
a=rtcp-fb:37 goog-remb
a=rtcp-fb:37 transport-cc
a=rtcp-fb:37 ccm fir
a=rtcp-fb:37 nack
a=rtcp-fb:37 nack pli
a=fmtp:37 profile-id=3
a=rtpmap:38 rtx/90000
a=fmtp:38 apt=37
a=rtpmap:102 H264/90000
a=rtcp-fb:102 goog-remb
a=rtcp-fb:102 transport-cc
a=rtcp-fb:102 ccm fir
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=rtpmap:103 rtx/90000
a=fmtp:103 apt=102
a=rtpmap:104 H264/90000
a=rtcp-fb:104 goog-remb
a=rtcp-fb:104 transport-cc
a=rtcp-fb:104 ccm fir
a=rtcp-fb:104 nack
a=rtcp-fb:104 nack pli
a=fmtp:104 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f
a=rtpmap:105 rtx/90000
a=fmtp:105 apt=104
a=rtpmap:106 H264/90000
a=rtcp-fb:106 goog-remb
a=rtcp-fb:106 transport-cc
a=rtcp-fb:106 ccm fir
a=rtcp-fb:106 nack
a=rtcp-fb:106 nack pli
a=fmtp:106 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:107 rtx/90000
a=fmtp:107 apt=106
a=rtpmap:108 H264/90000
a=rtcp-fb:108 goog-remb
a=rtcp-fb:108 transport-cc
a=rtcp-fb:108 ccm fir
a=rtcp-fb:108 nack
a=rtcp-fb:108 nack pli
a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
a=rtpmap:109 rtx/90000
a=fmtp:109 apt=108
a=rtpmap:127 H264/90000
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 transport-cc
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d001f
a=rtpmap:125 rtx/90000
a=fmtp:125 apt=127
a=rtpmap:39 H264/90000
a=rtcp-fb:39 goog-remb
a=rtcp-fb:39 transport-cc
a=rtcp-fb:39 ccm fir
a=rtcp-fb:39 nack
a=rtcp-fb:39 nack pli
a=fmtp:39 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=4d001f
a=rtpmap:40 rtx/90000
a=fmtp:40 apt=39
a=rtpmap:41 H264/90000
a=rtcp-fb:41 goog-remb
a=rtcp-fb:41 transport-cc
a=rtcp-fb:41 ccm fir
a=rtcp-fb:41 nack
a=rtcp-fb:41 nack pli
a=fmtp:41 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=f4001f
a=rtpmap:42 rtx/90000
a=fmtp:42 apt=41
a=rtpmap:43 H264/90000
a=rtcp-fb:43 goog-remb
a=rtcp-fb:43 transport-cc
a=rtcp-fb:43 ccm fir
a=rtcp-fb:43 nack
a=rtcp-fb:43 nack pli
a=fmtp:43 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=f4001f
a=rtpmap:44 rtx/90000
a=fmtp:44 apt=43
a=rtpmap:45 AV1/90000
a=rtcp-fb:45 goog-remb
a=rtcp-fb:45 transport-cc
a=rtcp-fb:45 ccm fir
a=rtcp-fb:45 nack
a=rtcp-fb:45 nack pli
a=rtpmap:46 rtx/90000
a=fmtp:46 apt=45
a=rtpmap:47 AV1/90000
a=rtcp-fb:47 goog-remb
a=rtcp-fb:47 transport-cc
a=rtcp-fb:47 ccm fir
a=rtcp-fb:47 nack
a=rtcp-fb:47 nack pli
a=fmtp:47 profile=1
a=rtpmap:48 rtx/90000
a=fmtp:48 apt=47
a=rtpmap:112 H264/90000
a=rtcp-fb:112 goog-remb
a=rtcp-fb:112 transport-cc
a=rtcp-fb:112 ccm fir
a=rtcp-fb:112 nack
a=rtcp-fb:112 nack pli
a=fmtp:112 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f
a=rtpmap:113 rtx/90000
a=fmtp:113 apt=112
a=rtpmap:114 red/90000
a=rtpmap:115 rtx/90000
a=fmtp:115 apt=114
a=rtpmap:116 ulpfec/90000
a=rtpmap:49 flexfec-03/90000
a=rtcp-fb:49 goog-remb
a=rtcp-fb:49 transport-cc
a=fmtp:49 repair-window=10000000

SRS返回的远端Answer

SRS在srs_app_rtc_api.cpp文件中的SrsGoApiRtcPlay类中处理offer请求,返回内容如下
SRS返回的远端Answer
远端Answer内容如下:

v=0  // 会话级描述:SDP协议版本,固定为0
o=SRS/4.0.245(Leo) 17778048 2 IN IP4 0.0.0.0   // 会话级描述
s=SRSPlaySession
t=0 0
a=ice-lite
a=group:BUNDLE 0 1
a=msid-semantic: WMS live/livestream
m=audio 9 UDP/TLS/RTP/SAVPF 111
c=IN IP4 0.0.0.0
a=ice-ufrag:j0w47g4z
a=ice-pwd:879b5n40s824s1985h3z60s77a8132v1
a=fingerprint:sha-256 A8:83:2B:5D:FF:E2:5A:14:6C:0A:24:A0:11:C3:01:8A:4A:8E:AF:3F:AC:B6:67:EE:3C:4B:47:07:7E:7B:D9:6F
a=setup:passive
a=mid:0
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=sendonly
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=ssrc:3459677730 cname:648fef7tl720yj49
a=ssrc:3459677730 label:audio-8804l2a1
a=candidate:0 1 udp 2130706431 124.221.111.76 8000 typ host generation 0
m=video 9 UDP/TLS/RTP/SAVPF 106
c=IN IP4 0.0.0.0
a=ice-ufrag:j0w47g4z
a=ice-pwd:879b5n40s824s1985h3z60s77a8132v1
a=fingerprint:sha-256 A8:83:2B:5D:FF:E2:5A:14:6C:0A:24:A0:11:C3:01:8A:4A:8E:AF:3F:AC:B6:67:EE:3C:4B:47:07:7E:7B:D9:6F
a=setup:passive
a=mid:1
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=sendonly
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:106 H264/90000
a=rtcp-fb:106 transport-cc
a=rtcp-fb:106 nack
a=rtcp-fb:106 nack pli
a=fmtp:106 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=ssrc:3459677731 cname:648fef7tl720yj49
a=ssrc:3459677731 label:video-7h7733ci
a=candidate:0 1 udp 2130706431 124.221.111.76 8000 typ host generation 0 

总结

对比本地和远端SDP发现,浏览器提供的特性非常多,SRS提供的较少,SRS是Lite ICE客户端,无需进行连通性检测。

参考文档

https://blog.csdn.net/aggresss/article/details/109850434
https://www.livevideostack.cn/news/webrtc-sdp-details-and-analysis/
https://blog.csdn.net/zqxf123456789/article/details/109696266
RFC4566
从0打造音视频直播系统(李超)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/389911.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第二讲:ambari编译复盘,如何实现一次性成功编译ambari

上节课我们已经讲解了如何成功编译ambari源码,安装ambari-server rpm包以及成功部署ambari。本节课我们来复盘一下上节课的编译过程,以及思考如何实现一次性成功编译ambari。 要想一次性成功编译ambari,那么就需要将预置工作做好,比如: maven镜像源配置,node_moudle模块…

Go项目(商品微服务-2)

文章目录简介handler商品分类轮播图品牌和品牌与分类oss前端直传库存服务数据不一致redis 分布式锁小结简介 开发商品微服务 API 层类似的&#xff0c;将 user-web 目拷贝一份&#xff0c;全局替换掉 user-web修改 config 去掉不用的配置更新本地和远程 nacos 配置文件 把 pro…

OpenGL环境配置

方法一&#xff1a;1.下载GLFW点击GLFW跳转2.下载后解压3.下载glad&#xff0c;解压后4.用vs2019新建Cmake项目5.在新建的Cmake项目下建立depend文件夹在depend里放置我们下载解压的glad和glfw-3.3.8.bin.WIN646.项目中可以看到我们加进来的文件7.编写我们项目的CMakeLists.txt…

Condition 源码解读

一、Condition 在并发情况下进行线程间的协调&#xff0c;如果是使用的 synchronized 锁&#xff0c;我们可以使用 wait/notify 进行唤醒&#xff0c;如果是使用的 Lock 锁的方式&#xff0c;则可以使用 Condition 进行针对性的阻塞和唤醒&#xff0c;相较于 wait/notify 使用…

路径规划-人工势场法

一.基本思想 目标点对机器人产生吸引力&#xff0c;障碍物对机器人产生排斥力&#xff1b; 所有力的合成构成机器人的控制律 二. 主要步骤 1.构建人工势场 目标点&#xff1a;吸引势场 障碍物&#xff1a;排斥势场 2.根据人工势场计算力 对势场求偏导 3.计算合力 计…

bpftrace 笔记

bpftrace -e BEFIN {printf("hello world!\n");}获取调用 vfs_read 函数的进程id, 每2s打印一次 bpftrace -e kprobe:vfs_read {ID pid;} interval:s:2 {printf{"ID:%d\n", ID);}用户态调试 bpftrace -e uprobe:/*/a.out:and {printf("ID:%d\n&qu…

费解的开关/翻硬币

&#x1f331;博客主页&#xff1a;大寄一场. &#x1f331;系列专栏&#xff1a; 算法 &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 题目&#xff1a;费解的开关 你玩过“拉灯”游戏吗&#xff1f; 25盏灯排成一个 55 的方形。 每一个灯都有一个开关&…

看完这篇入门性能测试

大家好&#xff0c;我是洋子。最近组内在进行服务端高并发接口的性能压测工作&#xff0c;起因是2023年2月2日&#xff0c;针对胡某宇事件进行新闻发布会直播&#xff0c;几十万人同时进入某媒体直播间&#xff0c;造成流量激增 从监控上可以看出&#xff0c;QPS到达某峰值后&…

brew安装问题

最近使用mac安装了Python和PyCharm&#xff0c;使用python中的绘制图像的turtle库后&#xff0c;执行报错&#xff1a; import _tkinter # If this fails your Python may not be configured for Tk ModuleNotFoundError: No module named _tkinter 查询后需在mac 命令行执行&…

【网络监控】Zabbix详细安装部署(最全)

文章目录Zabbix详细安装部署环境准备安装依赖组件访问初始化配置Zabbix详细安装部署 Zabbix 是一个高度集成的网络监控解决方案&#xff0c;可以提供企业级的开源分布式监控解决方案&#xff0c;由一个国外的团队持续维护更新&#xff0c;软件可以自由下载使用&#xff0c;运作…

【前端必看】极大提高开发效率的网页 JS 调试技巧

大家好&#xff0c;我是前端西瓜哥。本文讲解如何使用浏览器提供的工具进行 JS 代码的断点调试。 debugger 在代码中需要打断点的地方&#xff0c;加上 debugger&#xff0c;表示一个断点。浏览器代码执行到该位置时&#xff0c;会停下来&#xff0c;进入调试模式。 示例代码…

java内存模型的理解

java内存模型的理解并发问题产生的源头缓存导致的可见性问题线程切换导致的原子性问题编译优化带来的有序性问题小结Java内存模型: 解决可见性和有序性问题Java内存模型与JVM内存模型的区别volatile关键字Happens-Before规则小结思考题参考并发问题产生的源头 缓存导致的可见性…

【Verilog】——Verilog简介

目录 1.简介 2.什么是HDL以及HDL的功能 3.Verilog和C语言的比较 4.Verilog的用途 5.数字系统的抽象层次 1.系统级 2.算法级 3.RTL级&#xff08;寄存器变换级&#xff09; 6.数字系统抽象层级 7.自顶向下的结构化设计方法 8.Verilog建模 9.Verilog概述 10.Verilog模块的基本…

Django学习17 -- ManytoManyField

1. ManyToManyField &#xff08;参考&#xff1a;Django Documentation Release 4.1.4&#xff09; 类定义 class ManyToManyField(to, **options)使用说明 A many-to-many relationship. Requires a positional argument: the class to which the model is related, which w…

推导部分和——带权并查集

题解&#xff1a; 带权并查集 引言&#xff1a; 带权并查集是一种进阶的并查集&#xff0c;通常&#xff0c;结点i的权值等于结点i到根节点的距离&#xff0c;对于带权并查集&#xff0c;有两种操作需要掌握——Merge与Find&#xff0c;涉及到路径压缩与维护权值等技巧。 带…

用Python批量重命名文件

案例 今天,我们来整理文件夹中的文件,给某个文件夹下的所有文件重新命名。要求是给所有文件按照修改时间,按顺序在文件名前面加上编号。比如将文件资料.xlsx重命名为1. 资料.xlsx import osdef Get_modify_time(file):return os.path.getmtime(file) #获取文件修改时间path…

vue3的v-model指令

1. 普通input输入框双向绑定 <template><!-- 1. 普通input输入框双向绑定 --><!-- 其实等价于&#xff1a;<input :modelValue"title" update:modelValue"newTitle>titlenewTitle"/> --><input type"text" v-mod…

Junit测试框架

一、简介 Junit框架是一个开源的Java语言单元测试框架&#xff0c;Java方向使用最广泛的单元测试框架&#xff0c;使用Java开发者都应该学习Junit并能掌握单元测试的编写。 对于Junit和Selenium的关系&#xff1a;通俗点来说Selenium如果比喻为灯泡&#xff0c;那么Junit就是电…

【蓝桥杯集训15】求最短路存在负权边——spaf算法(2 / 4)

——SPFA 算法是 Bellman-Ford算法 的队列优化算法的别称 单源最短路&#xff0c;且图中没有负环就可以用spfa 目录 spaf求最短路模板 852. spfa判断负环 341. 最优贸易 - 3305. 作物杂交 - spaf求最短路模板 只有当一个点的前驱结点更新了&#xff0c;该节点才会得到…

操作系统——16.时间片轮转、优先级、多级反馈队列算法

这篇文章我们来看一下进程调度算法中的时间片轮转、优先级、多级反馈队列算法 目录 1.概述 2.时间片轮转调度算法&#xff08;RR&#xff0c;Round-Robin&#xff09; 3.优先级调度算法 4.多级反馈队列调度算法 5.分析对比 1.概述 首先&#xff0c;我们来看一下这篇文章…