客户端:
index.html
Learning WebRTC - Chapter 5: Connecting ClientsTogether
Login As
var connection = new WebSocket('ws://192.168.2.119:8888'),
name = "";
var loginPage = document.querySelector('#login-page'),
usernameInput = document.querySelector('#username'),
loginButton = document.querySelector('#login'),
callPage = document.querySelector('#call-page'),
theirUsernameInput = document.querySelector('#their-username'),
callButton = document.querySelector('#call'),
hangUpButton = document.querySelector('#hang-up');
callPage.style.display = "none";
// Login when the user clicks the button
loginButton.addEventListener("click",
function(event) {
name = usernameInput.value;
if (name.length > 0) {
send({
type: "login",
name: name
});
}
});
connection.onopen = function() {
console.log("Connected");
};
// Handle all messages through this callback
connection.onmessage = function(message) {
//alert(JSON.stringify(message.data));
console.log("Got message", message.data);
var data = JSON.parse(message.data);
switch (data.type) {
case "login":
onLogin(data.success);
break;
case "offer":
onOffer(data.offer, data.name);
break;
case "answer":
onAnswer(data.answer);
break;
case "candidate":
onCandidate(data.candidate);
break;
case "leave":
onLeave();
break;
default:
break;
}
};
connection.onerror = function(err) {
console.log("Got error", err);
};
// Alias for sending messages in JSON format
function send(message) {
if (connectedUser) {
message.name = connectedUser;
}
connection.send(JSON.stringify(message));
};
function onLogin(success) {
if (success === false) {
alert("Login unsuccessful, please try a different name.");
} else {
loginPage.style.display = "none";
callPage.style.display = "block";
// Get the plumbing ready for a call
startConnection();
}
};
callButton.addEventListener("click",
function() {
var theirUsername = theirUsernameInput.value;
if (theirUsername.length > 0) {
startPeerConnection(theirUsername);
}
});
hangUpButton.addEventListener("click",
function() {
send({
type: "leave"
});
onLeave();
});
function onOffer(offer, name) {
connectedUser = name;
yourConnection.setRemoteDescription(new RTCSessionDescription(offer));
yourConnection.createAnswer(function(answer) {
yourConnection.setLocalDescription(answer);
send({
type: "answer",
answer: answer
});
},
function(error) {
alert("An error has occurred");
});
}
function onAnswer(answer) {
yourConnection.setRemoteDescription(new RTCSessionDescription(answer));
}
function onCandidate(candidate) {
yourConnection.addIceCandidate(new RTCIceCandidate(candidate));
}
function onLeave() {
connectedUser = null;
theirVideo.src = null;
yourConnection.close();
yourConnection.onicecandidate = null;
yourConnection.onaddstream = null;
setupPeerConnection(stream);
}
function hasUserMedia() {
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
return !! navigator.getUserMedia;
}
function hasRTCPeerConnection() {
window.RTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
window.RTCSessionDescription = window.RTCSessionDescription || window.webkitRTCSessionDescription || window.mozRTCSessionDescription;
window.RTCIceCandidate = window.RTCIceCandidate || window.webkitRTCIceCandidate || window.mozRTCIceCandidate;
return !! window.RTCPeerConnection;
}
var yourVideo = document.querySelector('#yours'),
theirVideo = document.querySelector('#theirs'),
yourConnection,
connectedUser,
stream;
function startConnection() {
if (hasUserMedia()) {
navigator.getUserMedia({
video: true,
audio: true
},
function(myStream) {
stream = myStream;
yourVideo.src = window.URL.createObjectURL(stream);
if (hasRTCPeerConnection()) {
setupPeerConnection(stream);
} else {
alert("Sorry, your browser does not support WebRTC.");
}
},
function(error) {
console.log(error);
});
} else {
alert("Sorry, your browser does not support WebRTC.");
}
}
function setupPeerConnection(stream) {
var configuration = {
"iceServers": [{
"url": "stun:stun.1.google.com:19302"
}]
};
yourConnection = new RTCPeerConnection(configuration);
// Setup stream listening
yourConnection.addStream(stream);
yourConnection.onaddstream = function(e) {
theirVideo.src = window.URL.createObjectURL(e.stream);
};
// Setup ice handling
yourConnection.onicecandidate = function(event) {
if (event.candidate) {
send({
type: "candidate",
candidate: event.candidate
});
}
}
}
function startPeerConnection(user) {
connectedUser = user;
// Begin the offer
yourConnection.createOffer(function(offer) {
send({
type: "offer",
offer: offer
});
yourConnection.setLocalDescription(offer);
},
function(error) {
alert("An error has occurred.");
});
};
服务端:
index.js
var WebSocketServer = require('ws').Server,
wss = new WebSocketServer({
port: 8888
});
users = {};
wss.on('connection',
function(connection) {
console.log("User connected");
connection.on('message',
function(message) {
var data;
try {
data = JSON.parse(message);
} catch(e) {
console.log("Error parsing JSON");
data = {};
}
switch (data.type) {
case "login":
console.log("User logged in as", data.name);
if (users[data.name]) {
sendTo(connection, {
type: "login",
success: false
});
} else {
users[data.name] = connection;
connection.name = data.name;
sendTo(connection, {
type: "login",
success: true
});
}
break;
case "offer":
console.log("Sending offer to", data.name);
var conn = users[data.name];
if (conn != null) {
connection.otherName = data.name;
sendTo(conn, {
type: "offer",
offer: data.offer,
name: connection.name
});
}
break;
case "answer":
console.log("Sending answer to", data.name);
var conn = users[data.name];
if (conn != null) {
connection.otherName = data.name;
sendTo(conn, {
type: "answer",
answer: data.answer
});
}
break;
case "candidate":
console.log("Sending candidate to", data.name);
var conn = users[data.name];
if (conn != null) {
sendTo(conn, {
type: "candidate",
candidate: data.candidate
});
}
break;
case "leave":
console.log("Disconnecting user from", data.name);
var conn = users[data.name];
conn.otherName = null;
if (conn != null) {
sendTo(conn, {
type: "leave"
});
}
break;
default:
sendTo(connection, {
type: "error",
message: "Unrecognized command:" + data.type
});
break;
}
});
function sendTo(conn, message) {
conn.send(JSON.stringify(message));
}
connection.on('close',
function() {
if (connection.name) {
delete users[connection.name];
if (connection.otherName) {
console.log("Disconnecting user from", connection.otherName);
var conn = users[connection.otherName];
conn.otherName = null;
if (conn != null) {
sendTo(conn, {
type: "leave"
});
}
}
}
});
connection.send('{"hello":"hello123"}');
});
wss.on('listening',
function() {
console.log("Server started...");
});
将index.html 和client.js 放在web服务器上,像tomcat,apache,nginx...
确保在浏览器能访问,
用node 运行index.js,在8888端口提供websocket服务,注意对应修改client中的ip为运行index.js的服务器ip
开两个浏览器窗口A,B
A中用aaa登录,B中用bbb登录
登录后A中输入bbb然后call 会开启远程连接收到B的视频流,hang up 关闭远程链接
源码:http://download.csdn.net/detail/qq_24949727/9800426