主頁 > 企業開發 > 微信原生組件|基于小程式實作音視頻通話

微信原生組件|基于小程式實作音視頻通話

2022-09-22 08:33:59 企業開發

1 微信小程式原生推拉流組件功能簡介

本文將介紹如何使用微信小程式原生推拉流組件 <live-pusher> 和 <live-player> 進行推拉流,快速實作一個簡單的實時音視頻通話,

由于微信小程式原生推拉流組件使用起來比較復雜,推薦開發者使用即構封裝的音視頻SDK <zego-push> 和 <zego-player> 組件實作視頻通話,可參考 實作視頻通話,

2 實作微信小程式音視頻通話的前提條件

在實作基本的實時音視頻功能之前,請確保:

  • 已在專案中集成 ZEGO Express SDK 即構音視頻SDK,詳情請參考 快速開始 - 集成,
  • 已在 ZEGO 控制臺 創建專案,申請有效的 AppID 和 ServerSecret,詳情請參考 控制臺 - 專案管理 中的“專案資訊”,

3 即構音視頻SDK實作流程

用戶通過 ZEGO Express SDK 即構音視頻SDK進行視頻通話的基本流程為:

用戶 A、B 加入房間,用戶 B 預覽并將音視頻流推送到 ZEGO 云服務(推流),用戶 A 收到用戶 B 推送音視頻流的通知之后,在通知中播放用戶 B 的音視頻流(拉流),

下載.png

3.1 配置微信小程式后臺

在初始化 音視頻SDK 前,需要在 微信公眾平臺 中進行如下配置:

  • 服務器域名配置:在“小程式后臺 > 開發管理 > 開發設定 > 服務器域名”中,按照協議分類,將即構 Server 地址、LogUrl、以及用戶業務需要用到的地址填到指定的“request合法域名”或“socket合法域名”中,
    下載1.png

  • 相關功能開啟:在“小程式后臺 > 開發管理 > 介面設定 > 介面權限”中,打開 實時播放音視頻流實時錄制音視頻流 功能開關,
    下載2.png

3.2 即構音視頻SDK初始化

1. 創建音視頻通話界面

根據音視頻場景需要,為您的專案創建音視頻通話的用戶界面,我們推薦您在專案中添加如下元素:

  • 本地預覽視窗
  • 遠端視頻視窗
  • 結束按鈕
    下載3.png

小程式推流組件 <live-pusher> 中的 "video-width" 和 "video-height" 存在兼容性問題,可能會出現設定不生效的情況,

參考界面代碼:

<view wx:if="{{canShow== 1}}" >
  <view >
    <live-pusher  
    wx:if="{{pusher.url}}" 
    url="{{pusher.url}}"  
    mode="{{pusher.mode}}"
    autopush="{{pusher.autopush}}"
    enable-camera="{{pusher.enableCamera}}"
    enable-mic="{{pusher.enableMic}}"
    muted="{{!pusher.enableMic}}"
    enable-agc="{{pusher.enableAgc}}"
    enable-ans="{{pusher.enableAns}}"
    zoom="{{pusher.enableZoom}}"
    min-bitrate="{{pusher.minBitrate}}"
    max-bitrate="{{pusher.maxBitrate}}"
    video-
    video-height="{{pusher.videoHeight}}"
    beauty="{{pusher.beautyLevel}}"
    whiteness="{{pusher.whitenessLevel}}"
    orientation="{{pusher.videoOrientation}}"
    device-position="{{pusher.frontCamera}}"
    remote-mirror="{{pusher.enableRemoteMirror}}"
    local-mirror="{{pusher.localMirror}}"
    background-mute="{{pusher.enableBackgroundMute}}"
    audio-quality="{{pusher.audioQuality}}"
    audio-volume-type="{{pusher.audioVolumeType}}"
    audio-reverb-type="{{pusher.audioReverbType}}"
    waiting-image="{{pusher.waitingImage}}"
    beauty-style="{{pusher.beautyStyle}}"
    filter="{{pusher.filter}}"
    bindstatechange="onPushStateChange" 
    bindaudiovolumenotify="bindaudiovolumenotify"  
    bindnetstatus="onPushNetStateChange"
    waiting-image="https://storage.zego.im/downloads/pause_publish.png"></live-pusher>
      <live-player  wx:for="{{playerList}}" wx:key="streamID" id="{{item.id}}" 
      src= "https://www.cnblogs.com/zegodeveloper/archive/2022/09/21/{{item.url}}"
      mode= "RTC"
      autoplay= "{{item.autoplay}}"
      mute-audio= "{{item.muteAudio}}"
      mute-video= "{{item.muteVideo}}"
      orientation= "{{item.orientation}}"
      object-fit= "{{item.objectFit}}"
      min-cache= "{{item.minCache}}"
      max-cache= "{{item.maxCache}}"
      sound-mode= "{{item.soundMode}}"
      enable-recv-message= "{{item.enableRecvMessage}}"
      auto-pause-if-navigate= "{{item.autoPauseIfNavigate}}"
      auto-pause-if-open-native= "{{item.autoPauseIfOpenNative}}" enable-metadata="https://www.cnblogs.com/zegodeveloper/archive/2022/09/21/true" bindmetadatachange="binddatachange"  bindstatechange="onPlayStateChange" bindnetstatus="onPlayNetStateChange"></live-player>
  </view>
  <view >
    <view class='input-container'>
      <input value="https://www.cnblogs.com/zegodeveloper/archive/2022/09/21/{{roomID}}" bindinput="bindKeyInput" placeholder="請輸入房間 ID" placeholder-style='color: #b3b3b3; font-size: 14px;'  />
      <text ></text>
    </view>
    <view >
      <button bindtap="openRoom" data-role="1" data-option="videoAndAudio" hover- >
        加入房間(推流)
      </button>
     
      
      <button bindtap="logout" hover->退出房間</button>
    </view>
  </view>
</view>
<view >
  <button wx:if="{{canShow==0}}" open-type="openSetting" bindopensetting="settingCallback">
    授權使用攝像頭和麥克風
  </button>
</view>

2. 創建音視頻SDK引擎

創建 ZegoExpressEngine 引擎實體,將申請到的 AppID 傳入引數 “appID”,將獲取到的 Server 地址傳入引數 “server”,

// 初始化實體
zg = new ZegoExpressEngine(appID, server);

如果需要注冊回呼,開發者可根據實際需要,實作 ZegoEvent 中的某些方法,創建引擎后可通過呼叫 on 介面設定回呼,

zg.on('roomStateUpdate', (roomID, state, errorCode, extendedData) => {
    if (state == 'DISCONNECTED') {
        // 與房間斷開了連接
	// ...
    }

    if (state == 'CONNECTING') {
        // 與房間嘗試連接中
	// ...
    }

    if (state == 'CONNECTED') {
        // 與房間連接成功
	// ...
    }
})

3.3 登錄音視頻房間

1. 獲取房間登錄 Token

登錄房間需要用于驗證身份的 Token,獲取方式請參考 用戶權限控制,如需快速除錯,建議使用控制臺生成的臨時 Token,生成臨時 Token 的具體操作請參考 控制臺 - 專案管理,

2. 登錄音視頻房間

您可以呼叫 SDK 的 loginRoom 介面,傳入房間 ID 引數 “roomID”、“token” 和用戶引數 “user”,登錄房間,您可通過監聽 roomStateUpdate 回呼實時監控自己在本房間內的連接狀態,具體請參考 4.1 常見通知回呼 中的“4.1.1 我在房間內的連接狀態變化通知”,

roomID 和 user 的引數由您本地生成,但是需要滿足以下條件:

  • 同一個 AppID 內,需保證 “roomID” 全域唯一,
  • 同一個 AppID 內,需保證 “userID” 全域唯一,建議開發者將 “userID” 與自己業務的賬號系統進行關聯,

為避免錯過任何通知,您需要在登錄房間前先設定所有的監聽回呼(如房間狀態、用戶狀態、流狀態、推拉流狀態等),具體請參考 4.1 常見通知回呼 ,

// 登錄房間,成功則回傳 true
const result = await zg.loginRoom(roomID, token, {userID, userName});

3.4 將自己的音視頻流推送到 ZEGO 即構音視頻云

3.4.1 初始化小程式組件實體

呼叫 initContext 介面初始化小程式組件,

小程式組件中用于存盤推流屬性 pusher 和拉流屬性串列 playerList 兩個欄位需要傳給 SDK,SDK 后續將通過傳入的兩個欄位對相應的推拉流作狀態及視圖更新處理,

  • pusher 欄位中的屬性值請參考 ZegoWxPusherAttributes,
  • playerlist 欄位中的屬性值請參考 ZegoWxPlayerAttributes,
zg.initContext({
     wxContext: this,
     pushAtr: "pusher", // 物件名,物件屬性與 live-pusher 中的屬性為映射關系
     playAtr: "playerList" // 物件名,物件屬性與 live-player 中的屬性為映射關系
})

即構音視頻SDK 在內部會對推拉流實體進行操作以及視圖更新,開發者無需保存推拉流實體和呼叫小程式 setData 介面更新視圖,避免與 SDK 發生沖突,后續可通過 getPusherInstancegetPlayerInstance 介面獲取推拉流實體,

3.4.2 創建對應業務場景的 WXML

根據您的業務場景需求,撰寫 WXML 檔案,創建推拉流組件 <live-pusher> 和 <live-player>,

  • <live-pusher> 組件用于小程式的實時推送音視頻流功能,
  • <live-player> 組件用戶小程式的實時播放音視頻流功能,

WXML 的具體含義與用法請參考微信官網檔案中的介紹 WXML,

WXML 中的 pusher 與 playerList,必須與初始化小程式組件 initContext 中定義的這兩個欄位屬性名保持一致,后續 SDK 呼叫推拉流介面之后才能正確地進行狀態及視圖更新,

bindstatechange 表示播放狀態變化事件;bindaudiovolumenotify 表示播放音量大小通知;bindnetstatus 表示網路狀態通知,

<live-pusher  
    wx:if="{{pusher.url}}" 
    url="{{pusher.url}}"  
    mode="{{pusher.mode}}"
    autopush="{{pusher.autopush}}"
    enable-camera="{{pusher.enableCamera}}"
    enable-mic="{{pusher.enableMic}}"
    muted="{{!pusher.enableMic}}"
    enable-agc="{{pusher.enableAgc}}"
    enable-ans="{{pusher.enableAns}}"
    enable-ear-monitor="{{pusher.enableEarMonitor}}"
    auto-focus="{{pusher.enableAutoFocus}}"
    zoom="{{pusher.enableZoom}}"
    min-bitrate="{{pusher.minBitrate}}"
    max-bitrate="{{pusher.maxBitrate}}"
    video-
    video-height="{{pusher.videoHeight}}"
    beauty="{{pusher.beautyLevel}}"
    whiteness="{{pusher.whitenessLevel}}"
    orientation="{{pusher.videoOrientation}}"
    aspect="{{pusher.videoAspect}}"
    device-position="{{pusher.frontCamera}}"
    remote-mirror="{{pusher.enableRemoteMirror}}"
    local-mirror="{{pusher.localMirror}}"
    background-mute="{{pusher.enableBackgroundMute}}"
    audio-quality="{{pusher.audioQuality}}"
    audio-volume-type="{{pusher.audioVolumeType}}"
    audio-reverb-type="{{pusher.audioReverbType}}"
    waiting-image="{{pusher.waitingImage}}"
    beauty-style="{{pusher.beautyStyle}}"
    filter="{{pusher.filter}}"
    bindstatechange="onPushStateChange" 
    bindaudiovolumenotify="bindaudiovolumenotify"  
    bindnetstatus="onPushNetStateChange"
    waiting-image="https://storage.zego.im/downloads/pause_publish.png">
</live-pusher>
<live-player  wx:for="{{playerList}}" wx:key="streamID" id="{{item.id}}" 
      src= "https://www.cnblogs.com/zegodeveloper/archive/2022/09/21/{{item.url}}"
      mode= "RTC"
      autoplay= "{{item.autoplay}}"
      mute-audio= "{{item.muteAudio}}"
      mute-video= "{{item.muteVideo}}"
      orientation= "{{item.orientation}}"
      object-fit= "{{item.objectFit}}"
      min-cache= "{{item.minCache}}"
      max-cache= "{{item.maxCache}}"
      sound-mode= "{{item.soundMode}}"
      enable-recv-message= "{{item.enableRecvMessage}}"
      auto-pause-if-navigate= "{{item.autoPauseIfNavigate}}"
      auto-pause-if-open-native= "{{item.autoPauseIfOpenNative}}" enable-metadata="https://www.cnblogs.com/zegodeveloper/archive/2022/09/21/true" bindmetadatachange="binddatachange"  bindstatechange="onPlayStateChange" bindnetstatus="onPlayNetStateChange">
</live-player>

3.4.3 推送音視頻流到 ZEGO 即構音視頻云

必須完成初始化小程式組件實體和創建業務場景的 WXML 之后,才能呼叫 SDK 介面創建推流和拉流實體,

用戶呼叫 SDK 的 createPusher 介面創建推流實體,并通過呼叫實體物件上的 start 介面,傳入流 ID 引數 “streamID”,您可通過監聽 publisherStateUpdate 回呼知曉推流是否成功,具體請參考 4.1 常見通知回呼 中的“4.1.4 用戶推送音視頻流的狀態通知”,

“streamID” 由您本地生成,但是需要保證:

  • 同一個 AppID 下,“streamID” 全域唯一,如果同一個 AppID 下,不同用戶各推了一條 “streamID” 相同的流,后推流的用戶推流失敗,
  • “streamID” 長度不超過 256 位元組的字串,僅支持數字,英文字符和 “~”,“!”,“@”,“$”,“%”,“^”,“&”,“*”,“(”,“)”,“_”,“+”,“=”,“-”,“`”,“;”,“’”,“,”,“.”,“<”,“>”,“/”,“\”,
// 推流方登錄房間成功后觸發推流
 const pusher = zg.createPusher();
 pusher.start("streamID_xxx");

3.5 拉取其他用戶的音視頻

進行視頻通話時,我們需要拉取到其他用戶的音視頻,

用戶先呼叫 getPlayerInstance介面,根據傳入的流 ID 引數 “streamID”,獲取 streamID 對應的拉流實體,然后通過呼叫拉流實體物件的 play 介面開始拉流,您可通過監聽 playerStateUpdate 回呼知曉是否成功拉取音視頻,具體請參考 4.1 常見通知回呼 中的“4.1.5 用戶拉取音視頻流的狀態通知”,

遠端用戶推送的 “streamID” 可以從 roomStreamUpdate 回呼中獲得,具體回呼設定請參考 4.1 常見通知回呼 中的“4.1.3 房間內流狀態變更的通知”,

// 在 SDK 的回呼 roomStreamUpdate 中獲取拉流 streamID
// 當用戶加入或離開房間時,該事件被觸發
zg.on("roomStreamUpdate", (roomID, updateType, streamList) => {
    console.log("roomStreamUpdate", roomID, updateType, streamList);
    if (updateType === "ADD") {
        streamList.forEach(i => {
              zg.getPlayerInstance(i.streamID).play();
        })
    } else {
       streamList.forEach(i => {
              zg.getPlayerInstance(i.streamID).stop();
       })
    }
});

4 小程式音視頻通話的常用功能

4.1 常見音視頻房間通知回呼

4.1.1 我在房間內的連接狀態變化通知

roomStateUpdate:本地呼叫 loginRoom 加入房間時,您可通過監聽該回呼實時監控自己在本房間內的連接狀態,

用戶可以在回呼中根據不同狀態處理業務邏輯,

zg.on('roomStateUpdate', (roomID, state, errorCode, extendedData) => {
    if (state == 'DISCONNECTED') {
        // 與房間斷開了連接
	// ...
    }

    if (state == 'CONNECTING') {
        // 與房間嘗試連接中
	// ...
    }

    if (state == 'CONNECTED') {
        // 與房間連接成功
	// ...
    }
})

4.png

4.1.2 其他用戶進出房間的通知

roomUserUpdate:同一房間內的其他用戶進出房間時,您可通過此回呼收到通知,登錄房間后,當房間內有用戶新增或洗掉時,SDK 會通過該回呼通知,

只有呼叫 loginRoom 介面登錄房間時傳入 ZegoRoomConfig 配置,且 “userUpdate” 引數取值為 “true” 時,用戶才能收到 roomUserUpdate 回呼,

// 用戶狀態更新回呼
zg.on('roomUserUpdate', (roomID, updateType, userList) => {
    console.warn(
        `roomUserUpdate: room ${roomID}, user ${updateType === 'ADD' ? 'added' : 'left'} `,
        JSON.stringify(userList),
    );
});

4.1.3 房間內流狀態變更的通知

roomStreamUpdate:流狀態更新回呼,登錄房間后,當房間內有用戶新推送或洗掉音視頻流時,SDK 會通過該回呼通知,

// 流狀態更新回呼
zg.on('roomStreamUpdate', async (roomID, updateType, streamList, extendedData) => {
    if (updateType == 'ADD') {
        // 流新增,開始拉流
    } else if (updateType == 'DELETE') {
        // 流洗掉,停止拉流
    }
});

4.1.4 用戶推送音視頻流的狀態通知

  • 推流狀態事件

微信小程式會在 <live-pusher> 的 bindstatechange 系結的方法中通知出推流狀態事件,開發者需要:

a. 在 bindstatechange 系結的回呼函式中,呼叫 SDK 的 updatePlayerState 介面將推流狀態事件透傳給 SDK,

b. 在 SDK 的 publisherStateUpdate 回呼中處理推流的開始、失敗狀態,

// live-pusher 系結推流事件
onPushStateChange(e) {
    // 透傳推流事件給 SDK
    zg.updatePlayerState(this.data.publishStreamID, e);
},

// 推流后,服務器主動推過來的,流狀態更新
// NO_PUBLISH:未推流狀態,PUBLISH_REQUESTING:正在請求推流狀態,PUBLISHING:正在推流狀態
// state: "PUBLISHING" | "NO_PUBLISH" | "PUBLISH_REQUESTING";
zg.on("publisherStateUpdate", (result) => {
    console.log("publishStateUpdate", result.state);
});
  • 推流網路事件

微信小程式會在 <live-pusher> 的 bindnetstatus 系結的方法中通知出推流網路事件,開發者需要在對應的小程式回呼中,呼叫 SDK 的 updatePlayerNetStatus 介面將推流網路事件透傳給 SDK,

// live-pusher 系結網路狀態事件
onPushNetStateChange(e) {
    //透傳網路狀態事件給 SDK
    zg.updatePlayerNetStatus(this.data.publishStreamID, e);
},


// SDK 推流網路質量回呼
zg.on("publishQualityUpdate", (streamID, publishStats) => {
    console.log("publishQualityUpdate", streamID, publishStats);
});

4.1.5 用戶拉取音視頻流的狀態通知

  • 拉流狀態事件

微信小程式會在 <live-player> 的 bindstatechange 系結的方法中通知出拉流狀態事件,開發者需要:

a. 在 bindstatechange 系結的回呼函式中,呼叫 SDK 的 updatePlayerState 介面將拉流狀態事件透傳給 SDK,

b. 在 SDK 提供的 playerStateUpdate 回呼中處理拉流的開始或失敗狀態,

// live-player 系結的拉流事件
onPlayStateChange(e) {
    // 透傳拉流事件給 SDK
    zg.updatePlayerState(e.currentTarget.id, e);
},

// 服務器主動推過來的流的播放狀態
// 視頻播放狀態通知;state: "NO_PLAY" | "PLAY_REQUESTING" | "PLAYING";
zg.on("playerStateUpdate", (result) => {
    console.log("playStateUpdate", result.state);
});
  • 拉流網路事件

微信小程式會在 <live-player> 的 bindnetstatus 系結的方法中通知出拉流網路事件,開發者需要在對應的小程式回呼中,呼叫 SDK 的 updatePlayerNetStatus 介面將推流網路事件透傳給 SDK,

// live-player 系結網路狀態事件
onPlayNetStateChange(e) {
    // 透傳網路狀態事件給 SDK
    zg.updatePlayerNetStatus(playStreamID, e);
},

// SDK 拉流網路質量回呼
zg.on("playQualityUpdate", (playStreamID, playStats) => {
    console.log("playQualityUpdate", playStreamID, playStats);
});

4.2 停止fang jian音視頻通話

4.2.1 停止推送/拉取音視頻流

1. 停止推流

呼叫 SDK 的 getPusherInstance 介面獲取推流實體,并呼叫推流實體的 stop 方法停止推流,

// 停止推流
zg.getPusherInstance().stop();

2. 停止拉流

呼叫 SDK 的 getPlayerInstance 介面獲取拉流實體,并呼叫推流實體的 stop 方法停止拉流,

// 停止拉流
zg.getPlayerInstance(streamID).stop();

4.2.2 退出房間

呼叫 SDK 的 logoutRoom 介面退出房間,

zg.logoutRoom(roomID);

5 除錯視頻通話功能

在真機中運行專案,運行成功后,可以看到本端視頻畫面,

為方便體驗,ZEGO 提供了一個 Web 端除錯示例 ,在該頁面下,輸入相同的 AppID、RoomID,輸入一個不同的 UserID,即可加入同一房間與真機設備互通,當成功開始音視頻通話時,可以聽到遠端的音頻,看到遠端的視頻畫面,

6 視頻通話 API 呼叫時序

整個推拉流程序的 API 呼叫時序可參考下圖:
下載5.png

音視頻場景解決方案分享,更多詳情可搜索官網(https://zegoguanwang.datasink.sensorsdata.cn/t/pB)

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/509270.html

標籤:其他

上一篇:前端面試八股文

下一篇:react使用sass

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more