Ich versuche WebRTC aus der RealTime-Kommunikation mit WebRTC-Buch zu implementieren, und ich bekomme die folgenden Fehler. Ich verwende Socket.io 1.7.3 VersionTypeError: fn.bind ist keine Funktion
***Server.js***
C:\Users\raghav\node_modules\socket.io-adapter\index.js:196
if (fn) process.nextTick(fn.bind(null, null, sids));
^
TypeError: fn.bind is not a function
at Adapter.clients (C:\Users\raghav\node_modules\socket.io-adapter\index.js:196:31)
at Namespace.clients (C:\Users\raghav\node_modules\socket.io\lib\namespace.js:256:16)
at Socket.<anonymous> (C:\Users\raghav\WebstormProjects\NewsRoom\js\server.js:22:37)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at C:\Users\raghav\node_modules\socket.io\lib\socket.js:503:12
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickCallback (internal/process/next_tick.js:104:9)
Process finished with exit code 1
**webRTc.HTML**
Failed to load resource: net::ERR_CONNECTION_REFUSED
GET http://localhost:8181/socket.io/?EIO=3&transport=polling&t=LkCudeu net::ERR_CONNECTION_REFUSED
Unten ist der Code i
verwendetwebRTC.html
<!DOCTYPE html>
<html>rag
<head>
<title>Very simple WebRTC application with a Node.js signaling server</title>
</head>
<body>
<div id='mainDiv'>
<table border="1" width="100%">
<tr>
<th>
Local video
</th>
<th>
Remote video
</th>
</tr>
<tr>
<td>
<video id="localVideo" autoplay></video>
</td>
<td>
<video id="remoteVideo" autoplay></video>
</td>
</tr>
<tr>
<td align="center">
<textarea rows="4" cols="60"
id="dataChannelSend" disabled
placeholder="This will be enabled once
the data channel is up...">
</textarea>
</td>
<td align="center">
<textarea rows="4" cols="60"
id="dataChannelReceive" disabled>
</textarea>
</td>
</tr>
<tr>
<td align="center">
<button id="sendButton" disabled>Send</button>
</td>
<td></td>
</tr>
</table>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/adapterjs/0.14.1/adapter.min.js"></script>
<script src='js/completeNodeClientWithDataChannel.js'></script>
</body>
</html>
completeNodeClientWithDataChannel.js
'use strict';
// Look after different browser vendors' ways of calling the getUserMedia()
// API method:
// Opera --> getUserMedia
// Chrome --> webkitGetUserMedia
// Firefox --> mozGetUserMedia
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
// Clean-up function:
// collect garbage before unloading browser's window
window.onbeforeunload = function(e){
hangup();
}
// Data channel information
var sendChannel, receiveChannel;
var sendButton = document.getElementById("sendButton");
var sendTextarea = document.getElementById("dataChannelSend");
var receiveTextarea = document.getElementById("dataChannelReceive");
// HTML5 <video> elements
var localVideo = document.querySelector('#localVideo');
var remoteVideo = document.querySelector('#remoteVideo');
// Handler associated with Send button
sendButton.onclick = sendData;
// Flags...
var isChannelReady = false;
var isInitiator = false;
var isStarted = false;
// WebRTC data structures
// Streams
var localStream;
var remoteStream;
// PeerConnection
var pc;
// PeerConnection ICE protocol configuration (either Firefox or Chrome)
var pc_config = webrtcDetectedBrowser === 'firefox' ?
{'iceServers':[{'url':'stun:23.21.150.121'}]} : // IP address
{'iceServers': [{'url': 'stun:stun.l.google.com:19302'}]};
var pc_constraints = {
'optional': [
{'DtlsSrtpKeyAgreement': true}
]};
var sdpConstraints = {};
// Let's get started: prompt user for input (room name)
var room = prompt('Enter room name:');
// Connect to signaling server
var socket = io.connect("http://131.95.31.179:8181");
// Send 'Create or join' message to singnaling server
if (room !== '') {
console.log('Create or join room', room);
socket.emit('create or join', room);
}
// Set getUserMedia constraints
var constraints = {video: true, audio: true};
// From this point on, execution proceeds based on asynchronous events...
// getUserMedia() handlers...
function handleUserMedia(stream) {
localStream = stream;
attachMediaStream(localVideo, stream);
console.log('Adding local stream.');
sendMessage('got user media');
}
function handleUserMediaError(error){
console.log('navigator.getUserMedia error: ', error);
}
// Server-mediated message exchanging...
// 1. Server-->Client...
// Handle 'created' message coming back from server:
// this peer is the initiator
socket.on('created', function (room){
console.log('Created room ' + room);
isInitiator = true;
// Call getUserMedia()
navigator.getUserMedia(constraints, handleUserMedia, handleUserMediaError);
console.log('Getting user media with constraints', constraints);
checkAndStart();
});
// Handle 'full' message coming back from server:
// this peer arrived too late :-(
socket.on('full', function (room){
console.log('Room ' + room + ' is full');
});
// Handle 'join' message coming back from server:
// another peer is joining the channel
socket.on('join', function (room){
console.log('Another peer made a request to join room ' + room);
console.log('This peer is the initiator of room ' + room + '!');
isChannelReady = true;
});
// Handle 'joined' message coming back from server:
// this is the second peer joining the channel
socket.on('joined', function (room){
console.log('This peer has joined room ' + room);
isChannelReady = true;
// Call getUserMedia()
navigator.getUserMedia(constraints, handleUserMedia, handleUserMediaError);
console.log('Getting user media with constraints', constraints);
});
// Server-sent log message...
socket.on('log', function (array){
console.log.apply(console, array);
});
// Receive message from the other peer via the signaling server
socket.on('message', function (message){
console.log('Received message:', message);
if (message === 'got user media') {
checkAndStart();
} else if (message.type === 'offer') {
if (!isInitiator && !isStarted) {
checkAndStart();
}
pc.setRemoteDescription(new RTCSessionDescription(message));
doAnswer();
} else if (message.type === 'answer' && isStarted) {
pc.setRemoteDescription(new RTCSessionDescription(message));
} else if (message.type === 'candidate' && isStarted) {
var candidate = new RTCIceCandidate({sdpMLineIndex:message.label,
candidate:message.candidate});
pc.addIceCandidate(candidate);
} else if (message === 'bye' && isStarted) {
handleRemoteHangup();
}
});
// 2. Client-->Server
// Send message to the other peer via the signaling server
function sendMessage(message){
console.log('Sending message: ', message);
socket.emit('message', message);
}
// Channel negotiation trigger function
function checkAndStart() {
if (!isStarted && typeof localStream != 'undefined' && isChannelReady) {
createPeerConnection();
isStarted = true;
if (isInitiator) {
doCall();
}
}
}
// PeerConnection management...
function createPeerConnection() {
try {
pc = new RTCPeerConnection(pc_config, pc_constraints);
pc.addStream(localStream);
pc.onicecandidate = handleIceCandidate;
console.log('Created RTCPeerConnnection with:\n' +
' config: \'' + JSON.stringify(pc_config) + '\';\n' +
' constraints: \'' + JSON.stringify(pc_constraints) + '\'.');
} catch (e) {
console.log('Failed to create PeerConnection, exception: ' + e.message);
alert('Cannot create RTCPeerConnection object.');
return;
}
pc.onaddstream = handleRemoteStreamAdded;
pc.onremovestream = handleRemoteStreamRemoved;
if (isInitiator) {
try {
// Create a reliable data channel
sendChannel = pc.createDataChannel("sendDataChannel",
{reliable: true});
trace('Created send data channel');
} catch (e) {
alert('Failed to create data channel. ');
trace('createDataChannel() failed with exception: ' + e.message);
}
sendChannel.onopen = handleSendChannelStateChange;
sendChannel.onmessage = handleMessage;
sendChannel.onclose = handleSendChannelStateChange;
} else { // Joiner
pc.ondatachannel = gotReceiveChannel;
}
}
// Data channel management
function sendData() {
var data = sendTextarea.value;
if(isInitiator) sendChannel.send(data);
else receiveChannel.send(data);
trace('Sent data: ' + data);
}
// Handlers...
function gotReceiveChannel(event) {
trace('Receive Channel Callback');
receiveChannel = event.channel;
receiveChannel.onmessage = handleMessage;
receiveChannel.onopen = handleReceiveChannelStateChange;
receiveChannel.onclose = handleReceiveChannelStateChange;
}
function handleMessage(event) {
trace('Received message: ' + event.data);
receiveTextarea.value += event.data + '\n';
}
function handleSendChannelStateChange() {
var readyState = sendChannel.readyState;
trace('Send channel state is: ' + readyState);
// If channel ready, enable user's input
if (readyState == "open") {
dataChannelSend.disabled = false;
dataChannelSend.focus();
dataChannelSend.placeholder = "";
sendButton.disabled = false;
} else {
dataChannelSend.disabled = true;
sendButton.disabled = true;
}
}
function handleReceiveChannelStateChange() {
var readyState = receiveChannel.readyState;
trace('Receive channel state is: ' + readyState);
// If channel ready, enable user's input
if (readyState == "open") {
dataChannelSend.disabled = false;
dataChannelSend.focus();
dataChannelSend.placeholder = "";
sendButton.disabled = false;
} else {
dataChannelSend.disabled = true;
sendButton.disabled = true;
}
}
// ICE candidates management
function handleIceCandidate(event) {
console.log('handleIceCandidate event: ', event);
if (event.candidate) {
sendMessage({
type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate});
} else {
console.log('End of candidates.');
}
}
// Create Offer
function doCall() {
console.log('Creating Offer...');
pc.createOffer(setLocalAndSendMessage, onSignalingError, sdpConstraints);
}
// Signaling error handler
function onSignalingError(error) {
console.log('Failed to create signaling message : ' + error.name);
}
// Create Answer
function doAnswer() {
console.log('Sending answer to peer.');
pc.createAnswer(setLocalAndSendMessage, onSignalingError, sdpConstraints);
}
// Success handler for both createOffer()
// and createAnswer()
function setLocalAndSendMessage(sessionDescription) {
pc.setLocalDescription(sessionDescription);
sendMessage(sessionDescription);
}
// Remote stream handlers...
function handleRemoteStreamAdded(event) {
console.log('Remote stream added.');
attachMediaStream(remoteVideo, event.stream);
console.log('Remote stream attached!!.');
remoteStream = event.stream;
}
function handleRemoteStreamRemoved(event) {
console.log('Remote stream removed. Event: ', event);
}
// Clean-up functions...
function hangup() {
console.log('Hanging up.');
stop();
sendMessage('bye');
}
function handleRemoteHangup() {
console.log('Session terminated.');
stop();
isInitiator = false;
}
function stop() {
isStarted = false;
if (sendChannel) sendChannel.close();
if (receiveChannel) receiveChannel.close();
if (pc) pc.close();
pc = null;
sendButton.disabled=true;
}
server.js
var static = require('node-static');
var http = require('http');
// Create a node-static server instance
var file = new(static.Server)();
// We use the http module’s createServer function and
// rely on our instance of node-static to serve the files
var app = http.createServer(function (req, res) {
file.serve(req, res);
}).listen(8181);
// Use socket.io JavaScript library for real-time web applications
var io = require('socket.io').listen(app);
// Let's start managing connections...
io.sockets.on('connection', function (socket){
// Handle 'message' messages
socket.on('message', function (message) {
log('S --> got message: ', message);
// channel-only broadcast...
socket.broadcast.to(message.channel).emit('message', message);
});
// Handle 'create or join' messages
socket.on('create or join', function (room) {
var numClients = io.sockets.clients(room).length;
log('S --> Room ' + room + ' has ' + numClients + ' client(s)');
log('S --> Request to create or join room', room);
// First client joining...
if (numClients == 0){
socket.join(room);
socket.emit('created', room);
} else if (numClients == 1) {
// Second client joining...
io.sockets.in(room).emit('join', room);
socket.join(room);
socket.emit('joined', room);
} else { // max two clients
socket.emit('full', room);
}
});
function log(){
var array = [">>> "];
for (var i = 0; i < arguments.length; i++) {
array.push(arguments[i]);
}
socket.emit('log', array);
}
});