0

에 대한 정보는 Channel API과 브라우저 P2P 통신을 위해 this example by Dan Ristic을 따르려고합니다. 조용히 실패하고있는 것 같습니다. RTCDataChannel.onopen, RTCPeerConnection.onicecandidate 또는 RTCPeerConnection.ondatachannel 이벤트를 실행할 수 없습니다.Google 채널 API가 포함 된 RTCDataChannel

클라이언트 JS/HTML :

<html> 
<head> 
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script> 
<script type="text/javascript" src="/_ah/channel/jsapi"></script> 
<script> 
    $(document).ready(function(){ 

     var IS_CHROME = !!window.webkitRTCPeerConnection, 
      RTCPeerConnection = window.webkitRTCPeerConnection || mozRTCPeerConnection, 
      RTCIceCandidate = window.RTCIceCandidate || RTCSessionDescription, 
      RTCSessionDescription = window.RTCSessionDescription || mozRTCSessionDescription, 
      SESSION_ID = "12345", 
      weAreHost, 
      optionalRtpDataChannels = { 
       optional: [{RtpDataChannels: true}] 
      }, 
      mediaConstraints = { 
        optional: [], 
        mandatory: { 
         OfferToReceiveAudio: false, // Hmm!! 
         OfferToReceiveVideo: false // Hmm!! 
        } 
       }; 

     // Signaling Channel Object 
     function SignalingChannel(peerConnection) { 
      // Setup the signaling channel here 
      this.peerConnection = peerConnection; 
     } 

     function setChannelEvents(dataChannel) { 
      dataChannel.onmessage = function (event) { 
       console.log("I got data channel message: ", event.data); 
      } 

      dataChannel.onopen = function (event) { 
       dataChannel.send("RTCDataChannel Open!"); 
      } 

      dataChannel.error = function(event) { 
       console.log("data channel error:", event) 
      } 
     } 

     SignalingChannel.prototype.send = function(message) { 
      console.log("signal send:", message);   
      var url = "/api/signal/send/"; 
      url += weAreHost ? "client"+SESSION_ID : "host"+SESSION_ID; 
      $.ajax({ 
       type: "PUT", 
       url: url, 
       contentType: "application/json", 
       data: JSON.stringify(message) 
      }); 
     }; 

     SignalingChannel.prototype.onmessage = function(message) { 
      console.log("signal receive:", message); 
      // If we get a sdp we have to sign and return it 
      if (message.sdp != null) { 
      var that = this; 
      this.peerConnection.setRemoteDescription(new RTCSessionDescription(message), function() { 
       that.peerConnection.createAnswer(function (description) { 
       that.send(description); 
       }, null, mediaConstraints); 
      }); 
      } else { 
      this.peerConnection.addIceCandidate(new RTCIceCandidate(message.candidate)); 
      } 
     }; 

     function initiateConnection(input) { 
      weAreHost = input; 

      // setup signaling mechanism with Google Channel API 
      var url = "/api/signal/init/"; 
      url += weAreHost ? "host"+SESSION_ID : "client"+SESSION_ID; 
      $.post(url, "", function(response){  

       var channel = new goog.appengine.Channel(response.token); 
       var socket = channel.open(); 
       socket.onerror = function(){console.log(arguments);}; 
       socket.onclose = function(){console.log(arguments);}; 

       var closeSocket = function() { 
        if(socket) return socket.close(); 
        else return "google socket does not exist" 
       } 
       $(window).unload(closeSocket); 
       window.onbeforeunload = closeSocket; 

       socket.onopen = function() { 
        console.log("google socket opened"); 

        // Create a peer connection object 
        var connection = new RTCPeerConnection({ 
         iceServers: [ 
         { 'url': (IS_CHROME ? 'stun:stun.l.google.com:19302' : 'stun:23.21.150.121') } 
         ] 
        }, optionalRtpDataChannels); 

        // Initiate a signaling channel between two users 
        var signalingChannel = new SignalingChannel(connection); 

        connection.onicecandidate = function (event) { 
         console.log("onicecandidate:", event); 
         if (!event || !event.candidate) return; 
         signalingChannel.send({candidate:event.candidate}); 
        }; 

        // Effectively set SignalingChannel as google channel socket inbound event handler 
        socket.onmessage = function(input) { 
         console.log("received from google:", input);       
         var message = $.parseJSON(input.data); 
         signalingChannel.onmessage(message); 
        }; 

        // Only one client should initiate the connection, the other client should wait. 
        if(weAreHost) { 
         connection.ondatachannel = function(event) { 
          setChannelEvents(event.channel); 
         } 
        } else {       
         // Create client RTCDataChannel 
         var clientChannel = connection.createDataChannel("my_label", {reliable: false}); 
         setChannelEvents(clientChannel); 

         connection.createOffer(function (description) { 
          signalingChannel.send(description); 
         }, function(error){ 
          console.log(error); 
         }, mediaConstraints); 
        }   
       }; 
      }, "json"); 
     }; 

     // Create a button on the page so only one client initiates the connection.   
     $("#i-am-host").click(function() { 
      initiateConnection(true); 
     }); 
     $("#i-am-client").click(function() { 
      initiateConnection(false); 
     }); 
    }); 
</script> 
</head> 
<body> 
    <p id="i-am-host" style="background-color: green;">I AM HOST</p> 
    <p id="i-am-client" style="background-color: blue;">I AM CLIENT</p> 
</body> 
</html> 

앱 엔진 파이썬 :

from google.appengine.api import channel 

from django.shortcuts import render 
from django.http import HttpResponse 

import json 

def init(request, browser_id): 

    token = channel.create_channel(browser_id); 

    return HttpResponse(json.dumps({'token':token})) 

def send(request, browser_id): 

    channel.send_message(browser_id, request.body) 

    return HttpResponse() 

브라우저 콘솔 : 스타터

[HOST] 
received from google: 
Object {data: "{"sdp":"v=0\r\no=- 6804947085651458452 2 IN IP4 12…5000 webrtc-datachannel 1024\r\n","type":"offer"}"} 
test.html:34 
signal receive: 
Object {sdp: "v=0 
↵o=- 6804947085651458452 2 IN IP4 127.0.0.1 
↵s…id:data 
↵a=sctpmap:5000 webrtc-datachannel 1024 
↵", type: "offer"} 
test.html:22 
signal send: 
RTCSessionDescription {sdp: "v=0 
↵o=- 600524556593905006 2 IN IP4 127.0.0.1 
↵s=…id:data 
↵a=sctpmap:5000 webrtc-datachannel 1024 
↵", type: "answer"} 

[CLIENT] 
signal send: 
RTCSessionDescription {sdp: "v=0 
↵o=- 6804947085651458452 2 IN IP4 127.0.0.1 
↵s…id:data 
↵a=sctpmap:5000 webrtc-datachannel 1024 
↵", type: "offer"} 
test.html:82 
received from google: 
Object {data: "{"sdp":"v=0\r\no=- 600524556593905006 2 IN IP4 127…000 webrtc-datachannel 1024\r\n","type":"answer"}"} 
test.html:34 
signal receive: Object {sdp: "v=0 
↵o=- 600524556593905006 2 IN IP4 127.0.0.1 
↵s=…id:data 
↵a=sctpmap:5000 webrtc-datachannel 1024 
↵", type: "answer"} 

답변

4

Firefox는 RtpDataChannels을 지원하지 않으며 지원하지 않습니다. 스펙 호환 (및 고급) SCTP 데이터 채널 만 지원합니다. 선택적 구속 조건을 제거하면 다른 변경 사항을 적용하지 않고도 사용자에게 전환 할 수 있습니다.

SDP에 sctp 행이있는 것으로 보이는 것이 다소 이상합니다. rtp 데이터 채널을 사용하는 경우 http://googlechrome.github.io/webrtc/samples/web/content/datachannel/ 에 Google 샘플이 없습니다.

+0

나는 그것이 작동하는 것을 확인했습니다! 고맙습니다! 이 간단한 변경 만이 필요했습니다 :'optional : [{RtpDataChannels : false}]' – Lightbeard

1

, 당신은의 반대편에 peerConnection.onDataChannel 누락 데이터 채널 생성,

코드가 무언가 같이 될 것이다 : 전체 코드, 당신은 노력의 몇 시간 후이 link

+0

도움을 주셔서 감사합니다. 링크를 연구하고 이에 따라 변경했습니다. 나는 또한 RTCPeerConnection.onicecandidate와 mediaConstraints를 설정하는 것과 같은 다른 부분이 빠져 있음을 알았다. 불행히도, 나는 같은 결과를 얻고있다. – Lightbeard

+1

'''iceCandidates'''는'''''addIceCandidate''' 줄 앞에서'''console.log'''를 양측으로부터 수집하여 보내야 만합니다. 명확성 ... 또한 확인 https://www.webrtc-experiment.com/docs/WebRTC-PeerConnection.html – mido

0

을 확인할 수 있습니다

answerer.ondatachannel = function (event) { 
     answererDataChannel = event.channel; 
     answererDataChannel.binaryType = 'blob'; 
     setChannelEvents(answererDataChannel, 'answerer'); 
    }; 

... 


function setChannelEvents(channel, channelNameForConsoleOutput) { 
    channel.onmessage = function (event) { 
     console.debug(channelNameForConsoleOutput, 'received a message:', event.data); 
    }; 
    channel.onopen = function() { 
     channel.send('first text message over SCTP data ports'); 
    }; 
} 

, 나는 크롬 40.0에서 작동하도록 내 원래의 예를 얻을 수 있었다. 2214.93 및 오페라 27.0 (이 글의 최신 시점). why doesn't “onicecandidate” work? 많은 도움이되었습니다.

<html> 
<head> 
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script> 
<script type="text/javascript" src="/_ah/channel/jsapi"></script> 
<script> 
    $(document).ready(function(){ 

     var IS_CHROME = !!window.webkitRTCPeerConnection, 
      RTCPeerConnection = window.webkitRTCPeerConnection || mozRTCPeerConnection, 
      RTCIceCandidate = window.RTCIceCandidate || RTCSessionDescription, 
      RTCSessionDescription = window.RTCSessionDescription || mozRTCSessionDescription, 
      SESSION_ID = "123456", 
      weAreHost, 
      optionalRtpDataChannels = { 
       optional: [{RtpDataChannels: true}] 
      }, 
      mediaConstraints = { 
        optional: [], 
        mandatory: { 
         OfferToReceiveAudio: false, 
         OfferToReceiveVideo: false 
        } 
       }; 

     // Signaling Channel Object 
     function SignalingChannel(peerConnection) { 
      // Setup the signaling channel here 
      this.peerConnection = peerConnection; 
     } 

     function setChannelEvents(dataChannel) { 
      dataChannel.onmessage = function (event) { 
       console.log("I got data channel message: ", event.data); 
      } 

      dataChannel.onopen = function (event) { 
       dataChannel.send("######### SUCCESS ######### RTCDataChannel Open!"); 
      } 

      dataChannel.error = function(event) { 
       console.log("data channel error:", event) 
      } 
     } 

     function error(e) { 
      console.log(arguments); 
      throw new Error(e); 
     } 

     SignalingChannel.prototype.send = function(message) { 
      //console.log("signal send:", message);   
      var url = "/api/signal/send/"; 
      url += weAreHost ? "client"+SESSION_ID : "host"+SESSION_ID; 
      $.ajax({ 
       type: "PUT", 
       url: url, 
       contentType: "application/json", 
       data: JSON.stringify(message) 
      }); 
     }; 

     SignalingChannel.prototype.onmessage = function(message) { 
      //console.log("signal receive:", message);   
      var self = this; 

      if(message.type && message.type === "offer") { 
       var offer = new RTCSessionDescription(message); 
       this.peerConnection.setRemoteDescription(offer, function() { 
        self.peerConnection.createAnswer(function(answer) { 
         self.peerConnection.setLocalDescription(answer, function() { 
          self.send(answer); 
         }, error); 
        }, error, mediaConstraints); 
       }); 
      } else if(message.type && message.type === "answer") { 
       var answer = new RTCSessionDescription(message); 
       this.peerConnection.setRemoteDescription(answer, function(){    
       }, error); 
      } else {    
       this.peerConnection.addIceCandidate(new RTCIceCandidate(message.candidate)); 
      } 
     }; 

     function initiateConnection(input) { 
      weAreHost = input; 

      // setup signaling mechanism with Google Channel API 
      var url = "/api/signal/init/"; 
      url += weAreHost ? "host"+SESSION_ID : "client"+SESSION_ID; 
      $.post(url, "", function(response){  

       var channel = new goog.appengine.Channel(response.token); 
       var socket = channel.open(); 
       socket.onerror = error; 

       var closeSocket = function() { 
        if(socket) return socket.close(); 
        else return "google socket does not exist" 
       } 
       $(window).unload(closeSocket); 
       window.onbeforeunload = closeSocket; 

       socket.onopen = function() { 
        console.log("google socket opened"); 

        // Create a peer connection object 
        var connection = new RTCPeerConnection({ 
         iceServers: [ 
         { 'url': (IS_CHROME ? 'stun:stun.l.google.com:19302' : 'stun:23.21.150.121') } 
         ] 
        }, optionalRtpDataChannels); 


        // Initiate a signaling channel between two users 
        var signalingChannel = new SignalingChannel(connection); 

        connection.onicecandidate = function (event) { 
         //console.log("onicecandidate:", event); 
         if (!event || !event.candidate) return; 
         signalingChannel.send({candidate:event.candidate}); 
        }; 

        // Effectively set SignalingChannel as google channel socket inbound event handler 
        socket.onmessage = function(input) { 
         //console.log("received from google:", input);      
         var message = $.parseJSON(input.data); 
         signalingChannel.onmessage(message); 
        }; 

        // Only one client should initiate the connection, the other client should wait 
        if(weAreHost) { 
         connection.ondatachannel = function(event) { 
          setChannelEvents(event.channel); 
         } 
        } else { 
         // Create client RTCDataChannel 
         var clientChannel = connection.createDataChannel("my_label", {reliable: false}); 
         setChannelEvents(clientChannel); 

         // create offer and send to host 
         connection.createOffer(function (offer) {       
          connection.setLocalDescription(offer, function() {       
           signalingChannel.send(offer); 
          }, error); 
         }, error, mediaConstraints); 
        }   
       }; 
      }, "json").fail(error); 
     }; 

     // Create a button on the page so only one client initiates the connection.   
     $("#i-am-host").click(function() { 
      initiateConnection(true); 
     }); 
     $("#i-am-client").click(function() { 
      initiateConnection(false); 
     }); 
    }); 
</script> 
</head> 
<body> 
    <p id="i-am-host" style="background-color: green;">I AM HOST</p> 
    <p id="i-am-client" style="background-color: blue;">I AM CLIENT</p> 
    <br> 
    <p id="print">PRINT SIGNALING STATE<p> 
</body> 
</html> 

나는 신호에 대한 무료 Heroku가 서버와 PeerJS로 이동하기로 결정했습니다 : 파이어 폭스 작업을 얻는 운이 없었다. 필자의 의견으로는 WebRTC가 현재 너무 직접적으로 사용하기에는 너무 불안정합니다. 다음은 Chrome/FF/Opera에서 작동합니다.

<html> 
<head> 
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script> 
<script src="http://cdn.peerjs.com/0.3.9/peer.js"></script> 
<script> 
    $(document).ready(function(){ 

     var SESSION_ID = "1234"; 

     // Create a button on the page so only one client initiates the connection.   
     $("#i-am-host").click(function() { 

      var host = new Peer('host'+SESSION_ID, {host: 'my-peerjs.herokuapp.com', port: 80}); 
      host.on("connection", function(conn) { 
       conn.on('data', function(data) { 
        console.log(data); 
       }); 
      }); 

     }); 
     $("#i-am-client").click(function() { 

      var client = new Peer('client'+SESSION_ID, {host: 'my-peerjs.herokuapp.com', port: 80}); 
      var conn = client.connect('host'+SESSION_ID); 
      conn.on("open", function(){ 
       conn.send("SUCCESS!!"); 
      });  
     }); 
    }); 
</script> 
</head> 
<body> 
    <p id="i-am-host" style="background-color: green;">I AM HOST</p> 
    <p id="i-am-client" style="background-color: blue;">I AM CLIENT</p> 
</body> 
</html> 
관련 문제