一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

深入地研究WebRTC!Websocket服務(wù)器JscodeReact前端編碼器

LiveVideoStack ? 來(lái)源:LiveVideoStack ? 2020-09-22 09:58 ? 次閱讀

我的動(dòng)機(jī) 我們的目標(biāo)是制作一個(gè)精簡(jiǎn)易用的點(diǎn)對(duì)點(diǎn)文件共享網(wǎng)絡(luò)應(yīng)用程序,將更多的精力投入到用戶體驗(yàn)與簡(jiǎn)單地辦事上。這個(gè)網(wǎng)絡(luò)應(yīng)用程序不只是針對(duì)特定的個(gè)人群體服務(wù)的,而是針對(duì)整個(gè)社區(qū)服務(wù)。 既然有這么多文件共享網(wǎng)站,為什么我們還要做這些呢? 當(dāng)然,我也思考過(guò)這個(gè)問(wèn)題,但所有的這些網(wǎng)站都沒(méi)有真正地說(shuō)明過(guò)這些文件在哪里共享或存儲(chǔ)。這可能是一種隱私威脅,因?yàn)樵诋?dāng)前疫情的情況下,許多人或許經(jīng)常使用這些服務(wù)來(lái)共享文件甚至機(jī)密文件。使用安全的點(diǎn)對(duì)點(diǎn)連接和它的數(shù)據(jù)通道可以傳輸大量的文件,卻不需要存儲(chǔ)在任何服務(wù)器上,這使得它真正地結(jié)實(shí)與私有,因?yàn)橹挥羞B接的客戶端/對(duì)等端直接與中間服務(wù)器通信,不需要中間服務(wù)器進(jìn)行傳輸。 WebRTC使對(duì)等連接和數(shù)據(jù)通道成為可能。WebRTC基本上是一種相互通信與傳送數(shù)據(jù)的全球網(wǎng)絡(luò)方式,類(lèi)似于藍(lán)牙、NFC和WIFI數(shù)據(jù)共享。我們可以使用WebRTC實(shí)現(xiàn)跨平臺(tái)支持,因?yàn)樗腔诰W(wǎng)絡(luò)的。 讓我們更深入地研究WebRTC。 WebRTC

“WebRTC是一個(gè)免費(fèi)的開(kāi)放項(xiàng)目,通過(guò)簡(jiǎn)單的APIs為瀏覽器與移動(dòng)應(yīng)用程序提供實(shí)時(shí)通信(RTC)功能。WebRTC組件已經(jīng)進(jìn)行了優(yōu)化,以更好地滿足這一目的。” webrtc.org

好吧,假設(shè),一個(gè)“點(diǎn)對(duì)點(diǎn)”關(guān)聯(lián)考慮兩部設(shè)備之間發(fā)送的直接信息,而不需要服務(wù)器保存這些信息。聽(tīng)起來(lái)這對(duì)我們的情況很理想對(duì)吧?不幸的是,這不是WebRTC工作的方式!

圖為使用WebRTC進(jìn)行數(shù)據(jù)傳輸 盡管WebRTC實(shí)現(xiàn)了點(diǎn)對(duì)點(diǎn)連接,但它確實(shí)需要一個(gè)稱(chēng)為信令服務(wù)器的服務(wù)器,該服務(wù)器用于共享有關(guān)預(yù)期將其相互連接的設(shè)備的數(shù)據(jù)。這些微妙之處可以通過(guò)任何傳統(tǒng)的信息共享技術(shù)來(lái)共享。WebSockets在這里受到青睞,因?yàn)樗鼫p少了在一個(gè)龐大的建立關(guān)聯(lián)的系統(tǒng)中共享這些額外數(shù)據(jù)的惰性。 簡(jiǎn)而言之,信令服務(wù)器幫助建立連接,然而,當(dāng)連接建立后,服務(wù)器將不再涉及相關(guān)設(shè)備之間共享的信息。 一年前,當(dāng)我開(kāi)始我的第一個(gè)WebRTC項(xiàng)目時(shí),很難找到一個(gè)在“production”級(jí)別下工作得像樣的模型。后來(lái)我在網(wǎng)上找到了這個(gè)Youtube頻道編碼。開(kāi)發(fā)人員給出了關(guān)于可用于生產(chǎn)的WebRTC應(yīng)用程序的一些很好的例子。 WebRTC如何創(chuàng)建一個(gè)連接(技術(shù)) 好吧,沒(méi)有簡(jiǎn)單的方法來(lái)解釋這一點(diǎn),但我的看法是,在網(wǎng)絡(luò)上所有數(shù)量可觀的設(shè)備中,無(wú)論如何都必須有一個(gè)設(shè)備通過(guò)產(chǎn)生信號(hào)來(lái)啟動(dòng)連接,并將其發(fā)送到信令服務(wù)器上。這個(gè)對(duì)等點(diǎn)被稱(chēng)為啟動(dòng)器,在simple-peer(此項(xiàng)目中使用的模塊)中,當(dāng)創(chuàng)建一個(gè)啟動(dòng)器對(duì)等點(diǎn)時(shí),{initiator:true}會(huì)被傳遞給制作者/構(gòu)造函數(shù)。

如圖:信號(hào)服務(wù)器在運(yùn)行 當(dāng)我們得到對(duì)等點(diǎn)的信號(hào)信息時(shí),這些信息應(yīng)該通過(guò)某種方式通過(guò)信令服務(wù)器發(fā)送到不同的集線器。不同的集線器獲取此信息并嘗試與發(fā)起程序建立關(guān)聯(lián)。在這個(gè)過(guò)程中,這些對(duì)等體同樣產(chǎn)生它們的信號(hào)信息并被發(fā)送給發(fā)起方。發(fā)起方獲取此信息并嘗試與其余對(duì)等方建立連接。 瞧!這些設(shè)備現(xiàn)在已經(jīng)連接起來(lái),現(xiàn)在有一個(gè)數(shù)據(jù)通道,可以在沒(méi)有中間服務(wù)器的情況下共享信息。 盡量不要過(guò)分強(qiáng)調(diào)你無(wú)法理解WebRTC的上述工作方式以及簡(jiǎn)單對(duì)等點(diǎn)如何把它抽象化。當(dāng)我一開(kāi)始擺弄WebRTC時(shí),它嚇了我一大跳。接下來(lái)的部分將對(duì)這一點(diǎn)進(jìn)行更簡(jiǎn)單和細(xì)致的解釋。 與WebRTC共享文件(使用simple-peer)

const express = require("express"); const http = require("http"); const app = express(); const server = http.createServer(app); const socket = require("socket.io"); const io = socket(server); const users = {}; const socketToRoom = {}; io.on('connection', socket => { socket.on("join room", roomID => { if (users[roomID]) { const length = users[roomID].length; if (length === 2) { socket.emit("room full"); return; } users[roomID].push(socket.id); } else { users[roomID] = [socket.id]; } socketToRoom[socket.id] = roomID; const usersInThisRoom = users[roomID].filter(id => id !== socket.id); socket.emit("all users", usersInThisRoom); }); socket.on("sending signal", payload => { io.to(payload.userToSignal).emit('user joined', { signal: payload.signal, callerID: payload.callerID }); }); socket.on("returning signal", payload => { io.to(payload.callerID).emit('receiving returned signal', { signal: payload.signal, id: socket.id }); }); socket.on('disconnect', () => { const roomID = socketToRoom[socket.id]; let room = users[roomID]; if (room) { room = room.filter(id => id !== socket.id); users[roomID] = room; socket.broadcast.emit('user left', socket.id); } }); }); server.listen(process.env.PORT || 8000, () => console.log('server is running on port 8000')); Websocket服務(wù)器JscodeReact前端編碼器

import React, { useEffect, useRef, useState } from "react";import io from "socket.io-client";import Peer from "simple-peer";import styled from "styled-components";import streamSaver from "streamsaver"; const Container = styled.div` padding: 20px; display: flex; height: 100vh; width: 90%; margin: auto; flex-wrap: wrap;`; const worker = new Worker("../worker.js"); const Room = (props) => { const [connectionEstablished, setConnection] = useState(false); const [file, setFile] = useState(); const [gotFile, setGotFile] = useState(false); const chunksRef = useRef([]); const socketRef = useRef(); const peersRef = useRef([]); const peerRef = useRef(); const fileNameRef = useRef(""); const roomID = props.match.params.roomID; useEffect(() => { socketRef.current = io.connect("/"); socketRef.current.emit("join room", roomID); socketRef.current.on("all users", users => { peerRef.current = createPeer(users[0], socketRef.current.id); }); socketRef.current.on("user joined", payload => { peerRef.current = addPeer(payload.signal, payload.callerID); }); socketRef.current.on("receiving returned signal", payload => { peerRef.current.signal(payload.signal); setConnection(true); }); socketRef.current.on("room full", () => { alert("room is full"); }) }, []); function createPeer(userToSignal, callerID) { const peer = new Peer({ initiator: true, trickle: false, }); peer.on("signal", signal => { socketRef.current.emit("sending signal", { userToSignal, callerID, signal }); }); peer.on("data", handleReceivingData); return peer; } function addPeer(incomingSignal, callerID) { const peer = new Peer({ initiator: false, trickle: false, }); peer.on("signal", signal => { socketRef.current.emit("returning signal", { signal, callerID }); }); peer.on("data", handleReceivingData); peer.signal(incomingSignal); setConnection(true); return peer; } function handleReceivingData(data) { if (data.toString().includes("done")) { setGotFile(true); const parsed = JSON.parse(data); fileNameRef.current = parsed.fileName; } else { worker.postMessage(data); } } function download() { setGotFile(false); worker.postMessage("download"); worker.addEventListener("message", event => { const stream = event.data.stream(); const fileStream = streamSaver.createWriteStream(fileNameRef.current); stream.pipeTo(fileStream); }) } function selectFile(e) { setFile(e.target.files[0]); } function sendFile() { const peer = peerRef.current; const stream = file.stream(); const reader = stream.getReader(); reader.read().then(obj => { handlereading(obj.done, obj.value); }); function handlereading(done, value) { if (done) { peer.write(JSON.stringify({ done: true, fileName: file.name })); return; } peer.write(value); reader.read().then(obj => { handlereading(obj.done, obj.value); }) } } let body; if (connectionEstablished) { body = (

); } else { body = (

Once you have a peer connection, you will be able to share files

); } let downloadPrompt; if (gotFile) { downloadPrompt = (
You have received a file. Would you like to download the file?
); } return ( {body} {downloadPrompt} );}; export default Room; 在此Repo上找到整個(gè)代碼。如果你在瀏覽器中嘗試應(yīng)用上述代碼并選擇一些圖片文件(最好小于100KB),它會(huì)立即下載這些圖片文件。這是因?yàn)檫@個(gè)對(duì)等點(diǎn)位于一個(gè)類(lèi)似的瀏覽器中,而發(fā)送方處于提示狀態(tài)。 傳送和獲取的信息的大小是相等的。這表明我們可以選擇一次性移動(dòng)整個(gè)記錄! 為什么使用數(shù)據(jù)緩沖區(qū)而不是blob? 在我們過(guò)去的代碼中,如果我們選擇了一個(gè)巨大的文件(大于100KB),那么文檔很可能不會(huì)被發(fā)送,這是WebRTC通道的某些約束的直接結(jié)果。

如圖:數(shù)組緩沖區(qū)漫畫(huà)插圖(mozilla.org) 每個(gè)數(shù)組緩沖區(qū)一次只能有16KB的限制。簡(jiǎn)而言之,這意味著我們必須將文檔劃分成小數(shù)組緩沖區(qū)。 小文件可以通過(guò)WebRTC一次性發(fā)處,然而,對(duì)于大文檔,明智的做法是將文件隔離到較小的數(shù)組緩沖區(qū)中,并同樣發(fā)送每個(gè)部分。ArrayBuffer和Blob對(duì)象都有削減容量,這使得此過(guò)程更加簡(jiǎn)單。為此,如果你仔細(xì)查看代碼,你會(huì)發(fā)現(xiàn)我們使用了一個(gè)名為stream saver的模塊,它可以將數(shù)組緩沖區(qū)轉(zhuǎn)換回blob。 筆記 因?yàn)?a href="http://www.www27dydycom.cn/v/tag/852/" target="_blank">javascript是單線程的。處理大量數(shù)組緩沖區(qū)可能導(dǎo)致漂亮的UI無(wú)法響應(yīng)。為了解決這個(gè)問(wèn)題,我們將使用服務(wù)工作人員。一個(gè)服務(wù)工作人員是瀏覽器在后臺(tái)運(yùn)行的腳本,是與Web頁(yè)面分離的,這為不需要Web頁(yè)面或用戶交互的特性打開(kāi)大門(mén)。

let array = [];self.addEventListener("message", event => { if (event.data === "download") { const blob = new Blob(array); self.postMessage(blob); array = []; } else if (event.data === "abort") { array = []; } else { array.push(event.data); }}) 在服務(wù)工作程序中處理數(shù)組緩沖區(qū) 將文件劃分為數(shù)組緩沖區(qū)的優(yōu)點(diǎn) 雖然它可能會(huì)感覺(jué)分隔文件只是一些額外的代碼,并且會(huì)讓東西相互糾纏,但我們得到以下好處,并且可以幫助改進(jìn)我們的文檔共享應(yīng)用程序。

跨平臺(tái)支持(由mozilla.org提供說(shuō)明)

支持幾乎所有的瀏覽器

支持龐大的文檔大小——正如前面提到的,這是我們?yōu)槭裁匆獙?shí)現(xiàn)它的基本解釋。

一個(gè)更好的方法來(lái)破譯所發(fā)送信息的度量——通過(guò)在緩沖區(qū)中發(fā)送一個(gè)記錄,我們現(xiàn)在可以顯示信息,例如,發(fā)送的文檔的級(jí)別,發(fā)送記錄的速度等等。

識(shí)別未完成發(fā)送的文件——在無(wú)法完全發(fā)送文件的情況下,現(xiàn)在能夠以不同的方式獲取和處理文件。

結(jié)論 由于我們有一個(gè)使用WebRTC的文檔直接共享程序,而且它還利用了ArrayBuffer,我們現(xiàn)在應(yīng)該開(kāi)始考慮為應(yīng)用程序的生產(chǎn)做準(zhǔn)備的東西了。這些細(xì)節(jié)需要更多的探索,而不僅僅是遵循一個(gè)直接的教程。 可以補(bǔ)充的更多內(nèi)容:

信令服務(wù)器(STUN和TURN服務(wù)器)。

使多個(gè)對(duì)等連接可拓展。

當(dāng)WebRTC不能工作時(shí)才用的一種混合共享方式。

提高傳輸效率和速度。

我希望我已經(jīng)提供了足夠的信息讓你們開(kāi)始使用WebRTC應(yīng)用程序。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 編碼器
    +關(guān)注

    關(guān)注

    45

    文章

    3753

    瀏覽量

    136680
  • 服務(wù)器
    +關(guān)注

    關(guān)注

    12

    文章

    9603

    瀏覽量

    87022
  • WebRTC
    +關(guān)注

    關(guān)注

    0

    文章

    57

    瀏覽量

    11501

原文標(biāo)題:使用Webrtc和React Js在網(wǎng)絡(luò)上共享跨平臺(tái)的點(diǎn)對(duì)點(diǎn)文件

文章出處:【微信號(hào):livevideostack,微信公眾號(hào):LiveVideoStack】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    伺服電機(jī)編碼器怎么選型

    伺服電機(jī)編碼器的選型是一個(gè)綜合性的過(guò)程,需要考慮多個(gè)因素以確保所選編碼器能夠滿足系統(tǒng)的性能要求。以下是一些關(guān)鍵的選型步驟和考慮因素: 一、明確應(yīng)用需求 首先,需要明確伺服電機(jī)編碼器的應(yīng)用需求,包括
    的頭像 發(fā)表于 03-11 12:01 ?386次閱讀
    伺服電機(jī)<b class='flag-5'>編碼器</b>怎么選型

    DISCOAA編碼器類(lèi)型功能

    DISCOAA編碼器可能包括絕對(duì)編碼器和增量編碼器兩種類(lèi)型,其主要功能是將輸入信號(hào)進(jìn)行分析和處理,并將其轉(zhuǎn)換為數(shù)字信號(hào) ?。 關(guān)于類(lèi)型,雖然搜索結(jié)果中并未直接提及DISCOAA編碼器
    的頭像 發(fā)表于 02-20 13:47 ?235次閱讀

    伺服電機(jī)編碼器故障及維修

    伺服電機(jī)編碼器故障及維修,伺服電機(jī)編碼器4大常見(jiàn)故障,編碼器信號(hào)丟失或不穩(wěn)定,編碼器零點(diǎn)偏移,編碼器過(guò)熱,
    的頭像 發(fā)表于 01-21 14:49 ?1128次閱讀
    伺服電機(jī)<b class='flag-5'>編碼器</b>故障及維修

    編碼器種類(lèi)大觀:探索技術(shù)前沿與應(yīng)用創(chuàng)新

    ,再到集成了智能算法的智能編碼器,每一種編碼器都在其特定領(lǐng)域內(nèi)發(fā)揮著不可替代的作用。本文將帶您深入探索編碼器的多樣世界,揭示其技術(shù)奧秘與應(yīng)用創(chuàng)新。 旋轉(zhuǎn)
    的頭像 發(fā)表于 11-21 08:49 ?1109次閱讀

    編碼器類(lèi)型詳解:探索不同編碼技術(shù)的奧秘

    和反饋。然而,編碼器并非一種單一的技術(shù),而是涵蓋了多種類(lèi)型,每種類(lèi)型都有其獨(dú)特的工作原理和應(yīng)用場(chǎng)景。本文將帶您深入了解幾種常見(jiàn)的編碼器類(lèi)型,探索它們背后的技術(shù)奧秘。 光學(xué)編碼器 光學(xué)
    的頭像 發(fā)表于 11-19 08:58 ?1592次閱讀
    <b class='flag-5'>編碼器</b>類(lèi)型詳解:探索不同<b class='flag-5'>編碼</b>技術(shù)的奧秘

    增量編碼器與絕對(duì)值編碼器的區(qū)別

    增量編碼器與絕對(duì)值編碼器的區(qū)別:增量編碼器與絕對(duì)值編碼器在精度特點(diǎn)對(duì)比 增量編碼器的精度取決于脈沖的數(shù)量和測(cè)量的細(xì)分程度,通常情況下,其精度
    的頭像 發(fā)表于 11-18 16:38 ?2095次閱讀
    增量<b class='flag-5'>編碼器</b>與絕對(duì)值<b class='flag-5'>編碼器</b>的區(qū)別

    二進(jìn)制編碼器與絕對(duì)編碼器的區(qū)別

    編碼器是工業(yè)自動(dòng)化和機(jī)器人技術(shù)中不可或缺的組件,用于將機(jī)械位置或運(yùn)動(dòng)轉(zhuǎn)換為電信號(hào)。二進(jìn)制編碼器和絕對(duì)編碼器是兩種常見(jiàn)的編碼器類(lèi)型,它們各自有著獨(dú)特的特點(diǎn)和應(yīng)用場(chǎng)景。 二進(jìn)制
    的頭像 發(fā)表于 11-06 09:54 ?1032次閱讀

    增量編碼器和絕對(duì)值編碼器是什么

    工業(yè)編碼器是一類(lèi)傳感,是在工業(yè)自動(dòng)化閉環(huán)控制和數(shù)字化轉(zhuǎn)型物理感知重要的傳感。關(guān)于傳感的宣傳已很多,但是對(duì)于編碼器這么重要的傳感
    的頭像 發(fā)表于 10-22 14:23 ?854次閱讀
    增量<b class='flag-5'>編碼器</b>和絕對(duì)值<b class='flag-5'>編碼器</b>是什么

    磁電式編碼器好還是光電式編碼器

    夠提供非常準(zhǔn)確的位置反饋。這使得它在需要高精度和分辨率的應(yīng)用中表現(xiàn)尤為出色。 技術(shù)成熟 :光電式編碼器在市場(chǎng)上已經(jīng)存在多年,技術(shù)相對(duì)成熟,應(yīng)用廣泛。因此,用戶更容易找到適合其應(yīng)用需求的產(chǎn)品,并且技術(shù)支持和售后服務(wù)
    的頭像 發(fā)表于 10-12 10:01 ?1174次閱讀

    磁電編碼器和光電編碼器的區(qū)別

    磁電編碼器和光電編碼器是兩種不同類(lèi)型的編碼器,它們?cè)谠?、結(jié)構(gòu)、性能和應(yīng)用領(lǐng)域上都有所不同。 磁電編碼器和光電編碼器的區(qū)別 1. 引言
    的頭像 發(fā)表于 10-12 09:54 ?2533次閱讀

    請(qǐng)問(wèn)websocket庫(kù)怎么讀取服務(wù)器發(fā)來(lái)的數(shù)據(jù)?

    官方websocket庫(kù)怎么讀取服務(wù)器發(fā)來(lái)的數(shù)據(jù)?
    發(fā)表于 06-25 06:40

    編碼器的種類(lèi)及其特點(diǎn)

    編碼器是一種將模擬信號(hào)或物理量轉(zhuǎn)換為數(shù)字信號(hào)的設(shè)備,廣泛應(yīng)用于自動(dòng)化、測(cè)量、控制等多個(gè)領(lǐng)域。編碼器種類(lèi)繁多,每種編碼器都有其獨(dú)特的特點(diǎn)和應(yīng)用場(chǎng)景。本文將對(duì)常見(jiàn)的編碼器種類(lèi)及其特點(diǎn)進(jìn)行詳
    的頭像 發(fā)表于 06-13 14:50 ?1156次閱讀

    增量編碼器和絕對(duì)值編碼器的區(qū)別

    在工業(yè)自動(dòng)化和精密測(cè)量領(lǐng)域,編碼器是不可或缺的關(guān)鍵設(shè)備。編碼器能夠?qū)C(jī)械位移轉(zhuǎn)換為電信號(hào),以便于計(jì)算機(jī)或其他數(shù)字系統(tǒng)進(jìn)行處理。在編碼器的眾多類(lèi)型中,增量編碼器和絕對(duì)值
    的頭像 發(fā)表于 06-03 15:40 ?3771次閱讀

    旋轉(zhuǎn)編碼器的常見(jiàn)類(lèi)型

    詳細(xì)介紹旋轉(zhuǎn)編碼器的常見(jiàn)類(lèi)型,包括增量式編碼器和絕對(duì)式編碼器兩大類(lèi),并對(duì)它們的特點(diǎn)、工作原理、應(yīng)用場(chǎng)合等進(jìn)行深入探討。
    的頭像 發(fā)表于 05-29 15:59 ?1309次閱讀

    變頻編碼器的連接方式

    運(yùn)行的穩(wěn)定性和精確性。因此,變頻編碼器的連接方式對(duì)于整個(gè)系統(tǒng)的性能具有重要影響。本文將從多個(gè)角度詳細(xì)解析變頻編碼器的連接方式,包括其連接原理、具體步驟、注意事項(xiàng)等,旨在為讀者提
    的頭像 發(fā)表于 05-29 15:36 ?3456次閱讀