demo内容 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 <!DOCTYPE html> <html> <head> <title>demo2</title> </head> <style> </style> <body> <textarea id="dataChannelSend" disabled placeholder="Press Start, enter some text, then press Send."></textarea> <textarea id="dataChannelReceive" disabled></textarea> <div id="buttons"> <button id="startButton">Start</button> <button id="sendButton">Send</button> <button id="closeButton">Stop</button> </div> </body> <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script> <script type="text/javascript"> 'use strict'; let localConnection; let remoteConnection; let sendChannel; let receiveChannel; const dataChannelSend = document.querySelector('textarea#dataChannelSend'); const dataChannelReceive = document.querySelector('textarea#dataChannelReceive'); const startButton = document.querySelector('button#startButton'); const sendButton = document.querySelector('button#sendButton'); const closeButton = document.querySelector('button#closeButton'); startButton.onclick = createConnection; sendButton.onclick = sendData; closeButton.onclick = closeDataChannels; function enableStartButton() { startButton.disabled = false; } function disableSendButton() { sendButton.disabled = true; } function createConnection() { dataChannelSend.placeholder = ''; const servers = null; window.localConnection = localConnection = new RTCPeerConnection(servers); console.log('Created local peer connection object localConnection'); sendChannel = localConnection.createDataChannel('sendDataChannel'); console.log('Created send data channel'); localConnection.onicecandidate = e => { onIceCandidate(localConnection, e); }; sendChannel.onopen = onSendChannelStateChange; sendChannel.onclose = onSendChannelStateChange; window.remoteConnection = remoteConnection = new RTCPeerConnection(servers); console.log('Created remote peer connection object remoteConnection'); remoteConnection.onicecandidate = e => { onIceCandidate(remoteConnection, e); }; remoteConnection.ondatachannel = receiveChannelCallback; localConnection.createOffer().then( gotDescription1, onCreateSessionDescriptionError ); startButton.disabled = true; closeButton.disabled = false; } function onCreateSessionDescriptionError(error) { console.log('Failed to create session description: ' + error.toString()); } function sendData() { const data = dataChannelSend.value; sendChannel.send(data); console.log('Sent Data: ' + data); } function closeDataChannels() { console.log('Closing data channels'); sendChannel.close(); console.log('Closed data channel with label: ' + sendChannel.label); receiveChannel.close(); console.log('Closed data channel with label: ' + receiveChannel.label); localConnection.close(); remoteConnection.close(); localConnection = null; remoteConnection = null; console.log('Closed peer connections'); startButton.disabled = false; sendButton.disabled = true; closeButton.disabled = true; dataChannelSend.value = ''; dataChannelReceive.value = ''; dataChannelSend.disabled = true; disableSendButton(); enableStartButton(); } function gotDescription1(desc) { localConnection.setLocalDescription(desc); console.log(`Offer from localConnection\n${desc.sdp}`); remoteConnection.setRemoteDescription(desc); remoteConnection.createAnswer().then( gotDescription2, onCreateSessionDescriptionError ); } function gotDescription2(desc) { remoteConnection.setLocalDescription(desc); console.log(`Answer from remoteConnection\n${desc.sdp}`); localConnection.setRemoteDescription(desc); } function getOtherPc(pc) { return (pc === localConnection) ? remoteConnection : localConnection; } function getName(pc) { return (pc === localConnection) ? 'localPeerConnection' : 'remotePeerConnection'; } function onIceCandidate(pc, event) { getOtherPc(pc) .addIceCandidate(event.candidate) .then( () => onAddIceCandidateSuccess(pc), err => onAddIceCandidateError(pc, err) ); console.log(`${getName(pc)} ICE candidate: ${event.candidate ? event.candidate.candidate : '(null)'}`); } function onAddIceCandidateSuccess() { console.log('AddIceCandidate success.'); } function onAddIceCandidateError(error) { console.log(`Failed to add Ice Candidate: ${error.toString()}`); } function receiveChannelCallback(event) { console.log('Receive Channel Callback'); receiveChannel = event.channel; receiveChannel.onmessage = onReceiveMessageCallback; receiveChannel.onopen = onReceiveChannelStateChange; receiveChannel.onclose = onReceiveChannelStateChange; } function onReceiveMessageCallback(event) { console.log('Received Message'); dataChannelReceive.value = event.data; } function onSendChannelStateChange() { const readyState = sendChannel.readyState; console.log('Send channel state is: ' + readyState); if (readyState === 'open') { dataChannelSend.disabled = false; dataChannelSend.focus(); sendButton.disabled = false; closeButton.disabled = false; } else { dataChannelSend.disabled = true; sendButton.disabled = true; closeButton.disabled = true; } } function onReceiveChannelStateChange() { const readyState = receiveChannel.readyState; console.log(`Receive channel state is: ${readyState}`); } </script> </html>
工作原理 此代码使用RTCPeerConnection和RTCDataChannel来启用文本消息的交换。
此步骤中的大部分代码与RTCPeerConnection示例相同。
RTCDataChannel的语法有意类似于WebSocket,带有send()方法和消息事件。
注意dataConstraint的使用。可以配置数据通道以实现不同类型的数据共享 - 例如,优先考虑可靠的交付而不是性能。您可以在Mozilla Developer Network 上找到有关选项的更多信息。
加分项
WebRTC数据通道使用的协议使用SCTP ,默认使用可靠和有序的数据传输。在 RTCDataChannel 需要提供可靠的数据传输时或更重要的信息时使用它, 即使这可能意味着丢失一部分数据。查阅为什么使用sctp传输?
使用CSS改进页面布局,并将“占位符”属性添加到“dataChannelReceive”textarea。
在移动设备上测试页面。