webRTC介绍
webRTC是英文Web Real-Time Communication的缩写,中文翻译网页实时通信,是浏览器不需要服务器的中转,可以直接通信的技术
webRTC 应用
网上的很多教程都会包含实时视频的介绍,不过我感觉视频看起来很酷,不过却不是webRTC的使用难点,却明显增加webRTC的使用复杂度,可以略过
webRTC是客户端对客户端的单对单实时通信,但是还是需要服务器,就好比一个婚介所的作用
下面我们通过socket.io作为服务器端实现简单的聊天功能
实现步骤
发起方向服务器发出通知并初始化
RTCPeerConnection
服务器接收到通知通知接收并初始化
RTCPeerConnection
双方都监听
onicecandidate
事件,并在回调里面把event.candidate
上传到服务器双发都监听ondatachannel事件,并在回调里面给
event.channel
监听onmessage
事件发起方调用
createOffer
方法,并在这个方法的回调中给自己的RTCPeerConnection
实例设置setLocalDescription
,并向服务器发送自己的Description
接收方在服务器推送给自己的消息里面把5中的
Description
设置为自己的RTCPeerConnection
实例的RemoteDescription
,并调用createAnswer
方法,在此方法的回调之中设置setLocalDescription
,并把自己的Description
上传到服务器发起方接收到服务器推送给自己的
Description
,设置为LocalDescription
,至此双方连接建立
双方可以调用自己的channel的send方法发送文本消息
至于调用视频和音频,我觉着这部分使用起来比较简单,不绕
步骤就是一方的开启视频,获取视频流,添加到RTCPeerConnection实例中,连接的另外一方监听onaddstream事件,获取视频流,OK
多人会话的话,同一个RTCPeerConnection实例是不能够多人会话的。如果要多人会话,就要单对单建立多个连接。同样的步骤执行多次就可以了
客户端代码
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table width="800px">
<tr>
<td>
<video id="myVideo"></video>
</td>
<td>
<div style="height: 200px;overflow: auto"></div>
</td>
</tr>
<tr>
<td></td>
<td>
<textarea style="height: 200px;width: 400px" id="textarea"></textarea>
</td>
</tr>
</table>
<button id="start">开始</button>
<button id="stop">结束</button>
<button id="send">发送</button>
<script src='/socket.io/socket.io.js'></script>
<script src="js/index.js"></script>
</body>
</html>
js
var video = document.getElementById('video')
var localPeerConnection, remotePeerConnection
var localChannel
var socket = io.connect('http://localhost:8181')
// 打开页面即开启等待模式
startWaiting()
function startWaiting() {
var servers = {
"iceServers": [{
"url": "stun:stun.l.google.com:19302"
}]
}
var pc_constraints = {
optional: [{
DtlsSrtpKeyAgreement: true
}]
}
localPeerConnection = new RTCPeerConnection(servers, pc_constraints)
localChannel = localPeerConnection.createDataChannel('sendDataChannel', { reliable: true })
localPeerConnection.onicecandidate = function(event) {
if (event.candidate) {
socket.emit('onicecandidate', event.candidate)
}
}
localChannel.onopen = function() {
console.log('open')
}
localChannel.onclose = function() {
console.log('close')
}
localPeerConnection.ondatachannel = function(event) {
console.log(event.channel)
event.channel.onmessage = function(msg) {
console.log('event msg', msg)
}
}
socket.on('offer', function(desc) {
console.log('offer: ', desc)
localPeerConnection.setRemoteDescription(desc)
setRemote = true
localPeerConnection.createAnswer(function(desc) {
localPeerConnection.setLocalDescription(desc)
socket.emit('answer', desc)
}, function(error){console.log(error)})
})
socket.on('answer', function(desc) {
console.log('answer: ', desc)
localPeerConnection.setRemoteDescription(desc)
console.log('answer end')
setRemote = true
})
socket.on('onicecandidate', function(icecandidate) {
localPeerConnection.addIceCandidate(icecandidate)
})
}
document.getElementById('start').onclick = function() {
localPeerConnection.createOffer(function(desc) {
localPeerConnection.setLocalDescription(desc)
socket.emit('offer', desc)
}, function(error){console.log(error)})
}
document.getElementById('send').onclick = function() {
var value = document.getElementById('textarea').value
localChannel.send(value)
}
服务端代码
var static = require('node-static')
var http = require('http')
var file = new(static.Server)()
var app = http.createServer(function (req, res) {
file.serve(req, res);
}).listen(8181);
var io = require('socket.io').listen(app)
io.sockets.on('connection', function(socket) {
socket.on('offer',function(desc) {
socket.broadcast.emit('offer', desc)
})
socket.on('answer',function(desc) {
socket.broadcast.emit('answer', desc)
})
socket.on('onicecandidate', function(candidate) {
socket.broadcast.emit('onicecandidate', candidate)
})
socket.on('message', function(message) {
socket.broadcast.to(message.channel).emit('message', message.message)
})
})
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。