鍓嶈█銆嬪畠锛圵ebRTC锛夊厑璁哥綉椤靛簲鐢ㄧ▼搴忔垨缃戠珯鍦ㄦ祻瑙堝櫒涔嬮棿寤虹珛鐐瑰鐐癸紙Peer-to-Peer锛夎繛鎺ワ紝鏃犻渶涓粙锛屽疄鐜拌棰戞祦鍜岋紙鎴栵級闊抽娴佹垨鍏朵粬浠绘剰鏁版嵁鐨勪紶杈撯€濄€傝繖鏄疢DN涓婂WebRTC鐨勬弿杩般€傚垰寮€濮嬫帴瑙︾殑鏃跺€欙紝涓€鐩翠笉鑳界悊瑙ebRTC涓轰粈涔堣鍜學ebSocket閰嶅銆傝鐨勫緢娓呮锛屽鏋滄病鏈変腑浠嬬殑甯姪锛學ebSocket鎵紨浠€涔堣鑹插憿锛熸暣涓猈ebRTC璋冪敤鐨勫缓绔嬭繃绋嬫槸鎬庢牱鐨勶紵鍏堟潵鐪嬬湅鏈€缁堟晥鏋滐細1.鐩稿叧鎶€鏈湰渚嬩富瑕佷娇鐢╓ebRTC鍜學ebSocket锛歐ebRTC锛圵ebReal-TimeCommunication锛夊嵆缃戦〉鍗虫椂閫氳锛屾槸涓€绉嶆敮鎸佺綉椤垫祻瑙堝櫒杩涜瀹炴椂璇煶鎴栬棰戝璇濈殑API銆俉ebSocket鏄竴绉嶉€氳繃鍗曚釜TCP杩炴帴杩涜鍏ㄥ弻宸ラ€氫俊鐨勫崗璁€傚湪WebSocket涓紝娴忚鍣ㄥ拰鏈嶅姟鍣ㄥ彧闇€瑕佸畬鎴愪竴娆℃彙鎵嬶紝涓よ€呬箣闂村氨鍙互鐩存帴寤虹珛涓€涓暱杩炴帴锛岃繘琛屽弻鍚戞暟鎹紶杈撱€?.鍛煎彨寤虹珛杩囩▼绠€鍗曡涓€涓嬭繖涓繃绋嬨€傛瘮濡傛祻瑙堝櫒A瑕佸拰娴忚鍣˙杩涜闊宠棰戦€氳瘽锛欰鍜孊閮借繛鎺ュ埌淇′护鏈嶅姟鍣紙ws锛夛紱A鍒涘缓鏈湴瑙嗛锛岃幏鍙栦細璇濇弿杩板璞★紙offersdp锛変俊鎭紱A閫氳繃ws鍚態鍙戦€乷ffersdp锛汢鏀跺埌淇′护鍚庯紝鍒涘缓鏈湴瑙嗛锛岃幏鍙栦細璇濇弿杩板璞★紙answersdp锛変俊鎭紱B閫氳繃ws灏嗗簲绛攕dp鍙戦€佺粰A锛汚鍜孊寮€濮嬫墦娲烇紝閫氳繃ws鏀堕泦鍜屼氦鎹㈠啺淇℃伅锛涙墦瀛斿畬鎴愬悗锛孉鍜孊寮€濮嬪崗鍟嗗畨鍏ㄥ獟浣撻€氫俊鐨勫瘑閽ワ紱鑷虫锛孉鍜孊鍙互杩涜闊宠棰戦€氳瘽銆傚紩鐢ㄧ綉涓婂叧浜庡缓绔媁ebRTC鐨勬椂搴忓浘鍙兘鏇寸洿瑙傦細浠庝笂闈㈢殑杩囩▼鍙互鍙戠幇锛岄€氫俊鐨勫弻鏂瑰湪寤虹珛杩炴帴涔嬪墠闇€瑕佷氦鎹俊鎭紝杩欏氨鏄彁鍒扮殑WebSocket鐨勪綔鐢ㄥ紑澶达細淇′护鏈嶅姟鍣紝鐢ㄤ簬杞彂淇℃伅銆俉ebRTC涓嶄娇鐢ㄤ腑浠嬫剰鍛崇潃鐐瑰鐐硅繛鎺ュ缓绔嬪悗锛屼笉闇€瑕侀€氳繃绗笁鏂规湇鍔″櫒涓浆锛岃€屾槸鐩存帴鍦ㄤ袱涓疄浣擄紙娴忚鍣級涔嬮棿浼犺緭銆?銆佷唬鐮佺涓€姝ユ槸鑾峰彇video鏍囩锛岃繛鎺ヤ俊浠ゆ湇鍔″櫒锛屽垱寤篟TCPeerConnection瀵硅薄銆俁TCPeerConnection鐨勪綔鐢ㄦ槸鍦ㄤ袱涓猵eer涔嬮棿寤虹珛杩炴帴锛屽畠鐨勬瀯閫犲嚱鏁版敮鎸佷紶閫掍竴涓厤缃璞★紝鍖呮嫭ICE鐨勨€滄墦瀛斺€濓紙鍥犱负杩欎釜渚嬪瓙鏄湪鏈満娴嬭瘯鐨勶紝鎵€浠ヤ笉鏄繀椤荤殑锛夈€俢onstlocalVideo=document.querySelector('#local-video');constremoteVideo=document.querySelector('#remote-video');constsocket=newWebSocket('ws://localhost:8080');constpeer=newRTCPeerConnection();socket.onmessage=()=>{//todo}peer.ontrack=()=>{//todo}peer.onicecandidate=()=>{//todo}绗簩姝ヨ幏鍙栨湰鍦版憚鍍忓ご/楹﹀厠椋庯紙闇€瑕佹潈闄愭墠鑳戒娇鐢級锛屼竴鏃﹁幏寰楁湰鍦板獟浣撴祦锛圡ediaStream锛夛紝闇€瑕佸皢鍏朵腑鐨勬墍鏈夊獟浣撹建閬擄紙MediaStreamTrack锛夋坊鍔犲埌杞ㄩ亾闆嗕腑锛岃杞ㄩ亾闆嗗皢鍙戦€佺粰鍙︿竴涓猵eer銆俷avigator.mediaDevices.getUserMedia({video:true,audio:true}).then(stream=>{localVideo.srcObject=stream;stream.getTracks().forEach(track=>{peer.addTrack(track,stream);});});绗笁姝ュ垱寤哄彂璧疯€呬細璇濇弿杩板璞★紙createOffer锛夛紝璁剧疆鏈湴SDP锛坰etLocalDescription锛夛紝閫氳繃淇′护鏈嶅姟鍣ㄥ彂閫佺粰瀵圭锛屽彂璧蜂笌杩滅瀵圭鐨勬柊WebRTC杩炴帴銆俻eer.createOffer().then(offer=>{peer.setLocalDescription(offer);socket.send(JSON.stringify(offer));});褰撹皟鐢╯etLocalDescription鏂规硶鏃讹紝PeerConnection寮€濮嬫敹闆哻andidates锛坕ce淇℃伅锛夛紝骞跺悜peer鍙戦€乷ffer_ice銆傝繖閲岃ˉ鍏呬竴涓嬬涓€姝ヤ腑鐨刾eer.onicecandidate鍜宻ocket.onmessage銆俻eer鏀跺埌ice淇℃伅鍚庯紝閫氳繃璋冪敤addIceCandidate灏嗘敹鍒扮殑candidate淇℃伅浼犻€掔粰娴忚鍣ㄧ殑ICEagent銆俻eer.onicecandidate=e=>{if(e.candidate){socket.send(JSON.stringify({type:'offer_ice',iceCandidate:e.candidate}));}};socket.onmessage=e=>{const{type,sdp,iceCandidate}=JSON.parse(e.data);if(type==='offer_ice'){peer.addIceCandidate(iceCandidate);}}Step4receiver鎺ユ敹鍒皁ffer淇″彿鍚庯紝寮€濮嬭幏鍙朿amera/microphone锛屼笌initiator鐨勬搷浣滅浉鍚屻€傚悓鏃讹紝灏嗘敹鍒扮殑offerSDP鎸囧畾涓鸿繛鎺ョ殑remotepeer灞炴€э紙setRemoteDescription锛夛紝骞跺垱寤轰竴涓猺esponseSDP锛坈reateAnswer锛夊彂閫佺粰peer銆傝繖鏄涓€姝ヤ腑鐨剆ocket.onmessage銆俿ocket.onmessage=e=>{const{type,sdp,iceCandidate}=JSON.parse(e.data);if(type==='offer'){navigator.mediaDevices.getUserMedia();//涓庡彂璧疯€呬竴鑷达紝鐪佺暐constofferSdp=newRTCSessionDescription({type,sdp});peer.setRemoteDescription(offerSdp).then(()=>{peer.createAnswer(answer=>{socket.send(JSON.stringify(answer));peer.setLocalDescription(answer)});});}}娉ㄦ剰锛氳皟鐢╯etLocalDescription鏂规硶鏃讹紝浼氭敹闆嗗€欓€変俊鎭紝骞跺皢answer_ice鍙戦€佺粰peer銆備笌鍙戦€佹柟鐩稿悓锛屼笉鍐嶈禈杩般€傜浜旀锛屼笉鏂敹闆咺CE淇℃伅锛坥nicecandidate锛夛紝鍙戣捣鑰呭拰鍝嶅簲鑰呮渶缁堜細寤虹珛涓€涓渶浼樼殑杩炴帴妯″紡銆傛鏃朵細瑙﹀彂ontrack鍥炶皟锛岃幏鍙栧绔殑濯掍綋娴併€俻eer.ontrack=e=>{if(e&&e.streams){remoteVideo.srcObject=e.streams[0];}};4.鏈€鍚庢暣鍚堝彂璧锋柟鍜屽搷搴旀柟鐨勪唬鐮侊紝50琛屽乏鍙筹紝涓嶇畻鏍囬鍏氾紒鍝堝搱鍝堝搱鍝堚€︹€﹀畬鏁寸殑sample鐩稿叧浠g爜宸茬粡涓婁紶github.com/shushushv/webrtc-p2p锛屸瓙馃~
