2016-04-23 61 views
1

我的webrtc聊天代码出现问题。我无法在同伴之间建立联系。 PC1通过信号服务器发送优惠请求sucessfull,并且pc2添加候选人,但pc2不能发送候选人并回答pc1,为什么?Onicecandidate不在第二台电脑火灾

我几个小时都找不到错误,请帮我建立webrtc连接。

app.js

var app = require('express')(); 
var server = require('http').createServer(app); 

var virtualDirPath = process.env.virtualDirPath || ''; 
var io = require('socket.io')(server)//(server, { path: virtualDirPath + '/socket.io' }); 
var users = {}; 

server.listen(process.env.PORT || 8080, function() { 
    console.log('Подняли сервер на *:8080'); 
}); 

app.get('/', function (req, res) { 
    res.sendFile(__dirname + '/index.html'); 
}); 
app.get('/style.css', function (req, res) { 
    res.sendFile(__dirname + '/style.css'); 
}); 
app.get('/index.js', function (req, res) { 
    res.sendFile(__dirname + '/index.js'); 
}); 

io.on('connection', function (socket) { 

    socket.on('login', function(data){ 
     console.log('Зашел пользователь:', data.name); 

     //Не даем подключиться если пользователь уже в чате 
     if(users[data.name]) { 
      socket.emit('login', {state: 'taken'});   
     }else{ 
      socket.name = data.name; 
      users[data.name] = socket; 
      socket.broadcast.emit('newuser', {name: data.name}); 
      socket.emit('login', {name: data.name}); 
     } 
    }); 

    //format offer 
    socket.on('offer', function(data){//data.name, data.localDescription 
     console.log('Поулчили offer для:', data.to); 
     users[data.to].emit("offer", data); 
    }); 

    socket.on('answer', function(data){//data.name, data.localDescription 
     console.log('Поулчили answer для:', data.to); 
     console.log(data); 
     users[data.to].emit("offer", data); 
    }); 

    socket.on('candidate', function(data){//data.name, data.candidate 
     console.log('Поулчили candidate для:', data.to); 
     users[data.to].emit("candidate", data); 
    }); 

    socket.on('disconnect', function (data) { 
     console.log(data); 
     io.emit('user disconnected',data.to); 
     io.sockets.emit('quit', {name: data.from}) 
     delete users[data.from]; 
    }); 

}); 

的index.html:

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="utf-8"> 
    <title></title> 
    <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"> 
    <link rel="stylesheet" type="text/css" href="style.css"> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script> 
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script> 
</head> 
<body> 

<div class="modal fade" id="login-modal" tabindex="-1" role="dialog" data-keyboard="false" data-backdrop="static" aria-hidden="true" style="display: none;"> 
    <div class="modal-dialog"> 
    <div class="loginmodal-container"> 
     <h1>Войдите в чат</h1><br> 
     <form id="loginForm"> 
     <input type="text" name="username" placeholder="Username"> 
     <input type="submit" id="login" class="login loginmodal-submit" value="Вход"> 
     </form> 
    </div> 
    </div> 
</div> 


<script src="https://cdn.socket.io/socket.io-1.3.5.js"></script> 
<script src="index.js"></script> 

</body> 
</html> 

index.js:

var PeerConnection = window.mozRTCPeerConnection || window.webkitRTCPeerConnection; 
var IceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate; 
var SessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription; 

var socket; 
var peers = {}; 
var server = { 
    iceServers: [ 
    {url: "stun:23.21.150.121"}, 
    {url: "stun:stun.l.google.com:19302"} 
    ] 
}; 
var options = { 
    optional: [ 
    {DtlsSrtpKeyAgreement: true}, // требуется для соединения между Chrome и Firefox 
    {RtpDataChannels: true} // требуется в Firefox для использования DataChannels API 
    ] 
} 

$(document).ready(function() {  
     $('#login-modal').modal('show'); 

     //Логинимся. 
     $('#loginForm').on('submit', function(e) { 
     e.preventDefault(); 
     var name = $('input[name=username]').val(); 

     if (!name) { 
      alert('Вы не ввели логин'); 
      return; 
     }else{ 
      //подключаемся к сигнальному серверу 
      socket = io.connect(':8080', { 
      forceNew: true 
      }); 
      socket.emit('login',{name: name})   
     } 

     socket.on('login', function(data){ 
      var current_name = data.name; 

      if(data.state === 'taken'){ 
      alert('Пльзователь с таким ником уже находится в чате'); 
      }else if(data.name != undefined){ 
      console.log('Успешно зашли в чат'); 

      socket.on('newuser', function(data){ 
       console.log('receive newuser ', data.name); 
       peers[data.name] = { 
       cache: [] 
       };    

       // Создаем новое подключение 
       var pc = new PeerConnection(server, options); 

       // Инициализируем его 
       initConn(pc, data.name, current_name, "offer"); 

       // Сохраняем пир в списке 
       peers[data.name].connection = pc; 

       // Создаем DataChannel по которому и будет происходить обмен сообщениями 
       var channel = pc.createDataChannel("chatchannel", {}); 
       channel.owner = data.name; 
       peers[data.name].channel = channel; 

       // Устанавливаем обработчики событий канала 
       bindEvents(channel); 

       // Создаем SDP offer 
       pc.createOffer(function(offer) { 
       console.log('Установили локальный дескрипшен'); 
       pc.setLocalDescription(offer); 
       },function(err){ 
       console.log(err); 
       });    
      }); 

      socket.on('candidate', function(data){ 
       console.log('receive candidate from ', data.from); 
       createConnection(data.from, current_name); 
       var pc = peers[data.from].connection; 
       console.log(data.candidate); 
       pc.addIceCandidate(new IceCandidate(data.candidate)); 
      }); 

      socket.on('offer', function(data){ //name,localDescription 
       console.log('receive offer from ', data.from); 

       createConnection(data.from, current_name); 

       var pc = peers[data.from].connection; 

       console.log(pc); 

       pc.setRemoteDescription(new SessionDescription(data.localDescription)); 

       pc.createAnswer(function(answer) {     
        pc.setLocalDescription(answer); 
        console.log('answer created'); 
       },function(err){ 
        console.log(err); 
       }); 
      }); 

      socket.on('answer', function(data){ 
       console.log('receive answer from ', data.from);   
       var pc = peers[data.name].connection; 
       pc.setRemoteDescription(new SessionDescription(data.localDescription)); 
      }); 
      }else{ 
       alert('Ошибка при логине'); 
       location.reload(); 
      } 
     }); 

     });  

}); 


function createConnection(name, current_name){ 
    //Инициализируем подключение если его нет 
    console.log(peers[name]) 
    if (peers[name] === undefined){ 
    peers[name] = { 
     cache: [] 
    }; 
    var pc = new PeerConnection(server, options); 

    initConn(pc, name, current_name, 'answer'); 

    peers[name].connection = pc; 
    pc.ondatachannel = function(e) { 
     peers[name].channel = e.channel; 
     peers[name].channel.owner = name; 
     bindEvents(peers[name].channel); 
    } 
    console.log('CreateConnection'); 
    console.log(pc) 
    } 
} 

function initConn(pc, name, current_name, sdpType) { 
    console.log(pc); 
    console.log('-----------------------------------------') 
    pc.onicecandidate = function (event) { 
     if (event.candidate) { 
      // При обнаружении нового ICE кандидата добавляем его в список для дальнейшей отправки 
      peers[name].cache.push(event.candidate); 
     console.log('1'); 
     } else { 
      // Когда обнаружение кандидатов завершено, обработчик будет вызван еще раз, но без кандидата 
      // В этом случае мы отправялем пиру сначала SDP offer или SDP answer (в зависимости от SDP запроса) 

      socket.emit(sdpType, {to: name, from: current_name, localDescription: pc.localDescription}); 

     console.log('init conn'); 
     console.log(name); 
     console.log(current_name); 
     console.log(sdpType); 
      // ...а затем все найденные ранее ICE кандидаты 
      for (var i = 0; i < peers[name].cache.length; i++) { 
     socket.emit("candidate", {to: name, from: current_name, candidate: peers[name].cache[i]}); 
      } 
     } 
    } 

    pc.oniceconnectionstatechange = function (event) { 
     if (pc.iceConnectionState == "disconnected") { 
     //Пир отключился 
     //TODO добавить в список пользоавтелей data.name 

      delete peers[id]; 
     } 
    } 
} 

function bindEvents (channel) { 
    channel.onopen = function() { 
    //TODO добавить в список пользоавтелей channel.owner 

    }; 
    channel.onmessage = function (e) { 
    //TODO add text of message to chat div e.data 
    }; 
} 

PC2具有localDescription和remoteDescription。 PC2 PeerConnection等日志:

RTCPeerConnection {localDescription: RTCSessionDescription, remoteDescription: RTCSessionDescription, signalingState: "stable", iceGatheringState: "new", iceConnectionState: "new"…} 
iceConnectionState 
: 
"new" 
iceGatheringState 
: 
"new" 
localDescription 
: 
RTCSessionDescription 
sdp 
: 
"v=0 
↵o=- 4651396889672739307 2 IN IP4 127.0.0.1 
↵s=- 
↵t=0 0 
↵a=msid-semantic: WMS 
↵m=application 0 UDP/TLS/RTP/SAVPF 127 
↵c=IN IP4 0.0.0.0 
↵a=rtcp:9 IN IP4 0.0.0.0 
↵a=mid:data 
↵a=recvonly 
↵a=rtcp-mux 
↵a=rtpmap:127 google-data/90000 
↵" 
type 
: 
"answer" 
__proto__ 
: 
RTCSessionDescription 
onaddstream 
: 
null 
ondatachannel 
: 
(e) 
onicecandidate 
: 
(event) 
oniceconnectionstatechange 
: 
(event) 
onnegotiationneeded 
: 
null 
onremovestream 
: 
null 
onsignalingstatechange 
: 
null 
remoteDescription 
: 
RTCSessionDescription 
sdp 
: 
"v=0 
↵o=- 1739995165662969380 2 IN IP4 127.0.0.1 
↵s=- 
↵t=0 0 
↵a=group:BUNDLE data 
↵a=msid-semantic: WMS 
↵m=application 2740 UDP/TLS/RTP/SAVPF 127 
↵c=IN IP4 5.141.232.232 
↵b=AS:30 
↵a=rtcp:2120 IN IP4 5.141.232.232 
↵a=candidate:985767174 1 udp 2113937151 192.168.100.2 58907 typ host generation 0 
↵a=candidate:985767174 2 udp 2113937150 192.168.100.2 58909 typ host generation 0 
↵a=candidate:842163049 1 udp 1677729535 5.141.232.232 2740 typ srflx raddr 192.168.100.2 rport 58907 generation 0 
↵a=candidate:842163049 2 udp 1677729534 5.141.232.232 2120 typ srflx raddr 192.168.100.2 rport 58909 generation 0 
↵a=candidate:842163049 2 udp 1677729534 5.141.232.232 2910 typ srflx raddr 192.168.100.2 rport 58909 generation 0 
↵a=candidate:842163049 1 udp 1677729535 5.141.232.232 2830 typ srflx raddr 192.168.100.2 rport 58907 generation 0 
↵a=ice-ufrag:TYKF98cRmZWIRAm5 
↵a=ice-pwd:viHciQB6l36zfTuHdZCnJDPY 
↵a=fingerprint:sha-256 10:01:2C:0C:5D:B8:CC:32:15:D3:0D:0A:D3:50:BD:13:B8:9F:87:DF:97:1C:15:13:84:80:68:83:AB:FA:44:E8 
↵a=setup:actpass 
↵a=mid:data 
↵a=sendrecv 
↵a=rtcp-mux 
↵a=rtpmap:127 google-data/90000 
↵a=ssrc:2123048988 cname:pRuKm8BiQ79bLvJg 
↵a=ssrc:2123048988 msid:chatchannel chatchannel 
↵a=ssrc:2123048988 mslabel:chatchannel 
↵a=ssrc:2123048988 label:chatchannel 
↵" 
type 
: 
"offer" 
__proto__ 
: 
RTCSessionDescription 
signalingState 
: 
"stable" 
__proto__ 
: 
RTCPeerConnection 

回答

1

的问题,这tooks最后14小时我的生活是在Chrome和Firefox RTPDataChannels的那面旗帜 - 是过时的。不要使用它。保重你自己。现在一切都在进行。