ssl WebRTC没有连接到我的本地服务器,即使在本地浏览器或从我的移动终端

u3r8eeie  于 2023-04-12  发布在  其他
关注(0)|答案(1)|浏览(144)

我在nodejs中运行了这个服务器:

const express = require('express');
    const socketio = require('socket.io');
    const http = require('http');

    // Create server
    const app = express();
    const server = http.Server(app);

    // Map HTML and Javascript files as static
    app.use(express.static('public'));

    // Init Socket IO Server
    const io = socketio(server);

    // Array to map all clients connected in socket
    let connectedUsers = [];

    // Called whend a client start a socket connection
    io.on('connection', (socket) => {
    // It's necessary to socket knows all clients connected
    connectedUsers.push(socket.id);

    // Emit to myself the other users connected array to start a connection with each them
    const otherUsers = connectedUsers.filter(socketId => socketId !== socket.id);
    socket.emit('other-users', otherUsers);
    console.log(socket.id);

    // Send Offer To Start Connection
    socket.on('offer', (socketId, description) => {
        socket.to(socketId).emit('offer', socket.id, description);
    });

    // Send Answer From Offer Request
    socket.on('answer', (socketId, description) => {
        socket.to(socketId).emit('answer', description);
    });

    // Send Signals to Establish the Communication Channel
    socket.on('candidate', (socketId, candidate) => {
        socket.to(socketId).emit('candidate', candidate);
    });

    // Remove client when socket is disconnected
    socket.on('disconnect', () => {
        connectedUsers = connectedUsers.filter(socketId => socketId !== socket.id);
    });
    });

    // Return Index HTML when access root route
    app.get('/', (req, res) => {
    res.sendFile(path.resolve(__dirname, 'public', 'index.html'));
    });

    // Start server in port 3000 or the port passed at "PORT" env variable
    server.listen(process.env.PORT || 3000,
    () => console.log('Server Listen On: *:', process.env.PORT || 3000));

这就是site.js:

console.log('Main JS!');

    // Map All HTML Elements

    var messagesEl = document.querySelector('.messages');
    var messageInput = document.getElementById('message-input');
    var remoteVideo;
    $(document).ready(function () {

        var videoGrid = document.getElementById('video-grid');
        var localVideo = document.getElementById('local-video');
        var sendButton = document.getElementById('message-button');
        remoteVideo = document.getElementById('remote-video');

        // Open Camera To Capture Audio and Video
        navigator.mediaDevices.getUserMedia({ video: true, audio: true })
            .then(stream => {
                // Show My Video
                videoGrid.style.display = 'grid';
                localVideo.srcObject = stream;

                // Start a Peer Connection to Transmit Stream
                initConnection(stream);
            })
            .catch(error => console.log(error));

        // Map the 'message-button' click
        sendButton.addEventListener('click', () => {
            // GET message from input
            const message = messageInput.value;
            // Clean input
            messageInput.value = '';
            // Log Message Like Sended
            logMessage(`Send: ${message}`);

            // GET the channel (can be local or remote)
            const channel = localChannel || remoteChannel;
            // Send message. The other client will receive this message in 'onmessage' function from channel
            channel.send(message);
        });
    })

    const logMessage = (message) => {
      const newMessage = document.createElement('div');
      newMessage.innerText = message;
      messagesEl.appendChild(newMessage);
    };

    var pcConfig = {
        'iceServers': [
            {
                'urls': 'stun:stun.l.google.com:19302'
            }
        ]
    };
    const initConnection = (stream) => {
      const socket = io('http://192.168.1.217:3000',{transports: ['websocket']});
      let localConnection;
      let remoteConnection;
      let localChannel;
      let remoteChannel;

      // Start a RTCPeerConnection to each client
      socket.on('other-users', (otherUsers) => {
        // Ignore when not exists other users connected
        if (!otherUsers || !otherUsers.length) return;

        const socketId = otherUsers[0];

        // Ininit peer connection
          localConnection = new RTCPeerConnection(pcConfig);

        // Add all tracks from stream to peer connection
        stream.getTracks().forEach(track => localConnection.addTrack(track, stream));

        // Send Candidtates to establish a channel communication to send stream and data
        localConnection.onicecandidate = ({ candidate }) => {
          candidate && socket.emit('candidate', socketId, candidate);
        };

        // Receive stream from remote client and add to remote video area
        localConnection.ontrack = ({ streams: [ stream ] }) => {
          remoteVideo.srcObject = stream;
        };

        // Start the channel to chat
        localChannel = localConnection.createDataChannel('chat_channel');

        // Function Called When Receive Message in Channel
        localChannel.onmessage = (event) => logMessage(`Receive: ${event.data}`);
        // Function Called When Channel is Opened
        localChannel.onopen = (event) => logMessage(`Channel Changed: ${event.type}`);
        // Function Called When Channel is Closed
        localChannel.onclose = (event) => logMessage(`Channel Changed: ${event.type}`);

        // Create Offer, Set Local Description and Send Offer to other users connected
        localConnection
          .createOffer()
          .then(offer => localConnection.setLocalDescription(offer))
          .then(() => {
            socket.emit('offer', socketId, localConnection.localDescription);
          });
      });

      // Receive Offer From Other Client
      socket.on('offer', (socketId, description) => {
        // Ininit peer connection
          remoteConnection = new RTCPeerConnection(pcConfig);

        // Add all tracks from stream to peer connection
        stream.getTracks().forEach(track => remoteConnection.addTrack(track, stream));

        // Send Candidtates to establish a channel communication to send stream and data
        remoteConnection.onicecandidate = ({ candidate }) => {
          candidate && socket.emit('candidate', socketId, candidate);
        };

        // Receive stream from remote client and add to remote video area
        remoteConnection.ontrack = ({ streams: [ stream ] }) => {
          remoteVideo.srcObject = stream;
        };

        // Chanel Received
        remoteConnection.ondatachannel = ({ channel }) => {
          // Store Channel
          remoteChannel = channel;

          // Function Called When Receive Message in Channel
          remoteChannel.onmessage = (event) => logMessage(`Receive: ${event.data}`);
          // Function Called When Channel is Opened
          remoteChannel.onopen = (event) => logMessage(`Channel Changed: ${event.type}`);
          // Function Called When Channel is Closed
          remoteChannel.onclose = (event) => logMessage(`Channel Changed: ${event.type}`);
        }

        // Set Local And Remote description and create answer
        remoteConnection
          .setRemoteDescription(description)
          .then(() => remoteConnection.createAnswer())
          .then(answer => remoteConnection.setLocalDescription(answer))
          .then(() => {
            socket.emit('answer', socketId, remoteConnection.localDescription);
          });
      });

      // Receive Answer to establish peer connection
      socket.on('answer', (description) => {
        localConnection.setRemoteDescription(description);
      });

      // Receive candidates and add to peer connection
      socket.on('candidate', (candidate) => {
        // GET Local or Remote Connection
        const conn = localConnection || remoteConnection;
        conn.addIceCandidate(new RTCIceCandidate(candidate));
      });

    }

前端:

@page
    @model IndexModel
    <h1>Hello!</h1>

    <!-- My Video and Remote Video from connection -->
    <div id="video-grid">
        <video playsinline autoplay muted id="local-video"></video>
        <video playsinline autoplay id="remote-video"></video>
    </div>

    <!-- Input to send messages -->
    <div>
        <span style="font-weight: bold">Message: </span>
        <input type="text" id="message-input" title="Message to Send!">
        <button id="message-button">Send</button>
    </div>

    <!-- Area to Print Images -->
    <div class="messages"></div>

我所做的是,我已经设置了前端与site.js和index.html在IIS windows 10本地,使我可以测试和访问流在我的浏览器和移动终端。
成功地我已经设法让本地流工作,但远程流不工作,由于某种原因.我添加了一个回合服务器来解决这个问题.但我发现,在我的本地笔记本电脑/ PC上运行的服务器是不拿起连接到移动终端,甚至浏览器.
当我将此更改为“localhost”时,浏览器可以连接,本地和远程视频工作正常:

const socket = io('http://localhost:3000',{transports: ['websocket']});

但是,当我将IP地址更改为本地机器时,浏览器似乎无法连接到服务器,反过来,移动终端根本无法连接到服务器。
我已经在iis中添加了https,ssl到网站上,当我没有这样做时,移动终端本地视频不工作,但一旦我将ssl添加到网站上,本地视频就开始正常工作。
因此,我的问题是,远程流不是从移动的和浏览器设备显示。
这和ssl有什么关系吗?

unguejic

unguejic1#

是的,这是因为要在浏览器中访问相机/麦克风,页面应该具有安全上下文。
Mozilla docs:
getUserMedia()是一个强大的特性,只能在安全的上下文中使用;在不安全的上下文中,navigator.mediaDevices是未定义的,从而阻止了对getUserMedia()的访问。简而言之,安全上下文是使用HTTPS或file:///URL方案加载的页面,或者是从localhost加载的页面。
出于测试目的,可以通过使用ngrok等https代理或使用nginx等反向代理将本地主机请求代理到服务器来绕过此限制。此外,基于chromium-based的浏览器允许您传递--unsafely-treat-insecure-origin-as-secure="http://youraddress",这应该会授予“youraddress”http页面安全上下文。
对于生产,需要SSL。

相关问题