【问题标题】:WebSocket (Socket.io) connection Error - failed: Connection closed before receiving a handshake responseWebSocket(Socket.io)连接错误 - 失败:连接在收到握手响应之前关闭
【发布时间】:2021-07-12 18:48:10
【问题描述】:

我花了一整天的时间在网上寻找错误的解决方案

到 'wss://localhost/myapp/peerjs?key=peerjs&id=5c70da87-62c1-41dd-b1b1-e7aea5acc09b&token=j4n0nprnu6' 的 WebSocket 连接失败:在收到握手响应之前连接已关闭

我正在 express 服务器上开发这个 nodejs 应用程序。我在其中初始化 PeerServer 的快递服务器:

// Dependencies
const express = require('express')
const app = express()
const httpPort = process.env.PORT || 80
const httpsPort = 443
const { ExpressPeerServer } = require('peer')
const path = require('path')
const http = require('http')
const https = require('https')
const fs = require('fs')

// Certificate & credentials
const privateKey = fs.readFileSync(path.join(__dirname, 'certs', 'key.pem'))
const certificate = fs.readFileSync(path.join(__dirname, 'certs', 'cert.pem'))
const credentials = {
        key: privateKey,
        cert: certificate
}

const mainServer = http.createServer(app).listen(httpPort, () => { console.log('Main Server listening to port ' + httpPort) })
const httpsServer = https.createServer(credentials, app).listen(httpsPort, () => { console.log('Peer Server listening to port ' + httpsPort) })

const peerServer = ExpressPeerServer(mainServer, {
        debug: true,
        path: '/myapp'
})

//app.use('peerjs', peerServer)
app.use(peerServer)

const io = require('socket.io')(httpsServer)
const { v4: uuidV4 } = require('uuid')

app.set('view engine', 'ejs')
app.use(express.static('public'))

app.get('/', (req, res) => {
  res.redirect(`/${uuidV4()}`)
})

app.get('/:room', (req, res) => {
  res.render('room', { roomId: req.params.room })
  //console.log('Room Created / Joined')
})

io.on('connection', (socket) => {
    //console.log('IO Connectedd')
    socket.on('join-room', (roomId, userId) => {
        console.log(roomId, userId)
        socket.join(roomId)
        socket.to(roomId).emit('user-connected', userId)

        socket.on('disconnect', () => {
            socket.to(roomId).emit('user-disconnected', userId)
        })
    })
})

下面是我的客户端代码

const socket = io('/')
const videoGrid = document.getElementById('video-grid')
const myPeer = new Peer(undefined, {
    host: '/',
    port: '443',
    path: '/myapp'
})
const ownVideo = document.createElement('video') // Own Video
ownVideo.muted = true
const peers = {}
navigator.mediaDevices.getUserMedia({
    video: true,
    audio: true
}).then(stream => {
    addVideoStream(ownVideo, stream)

    myPeer.on('call', call => { // On Receiving Other Persons Call
        call.answer(stream) // Send Video Stream On Answer
        const video = document.createElement('video')
        call.on('stream', userVideoStream => { // Send Back Video Stream On Stream
            addVideoStream(video, userVideoStream)
        })
    })

    socket.on('user-connected', userId => { // Allow Self To Be Connected To Others
        console.log('User Connected: ' + userId)
        connectToNewUser(userId, stream)
    })
})

socket.on('user-disconnected', userId => {
    if (peers[userId]) peers[userId].close()
})

myPeer.on('open', id => {
    socket.emit('join-room', ROOM_ID, id)
})

function connectToNewUser(userId, stream) {
    const call = myPeer.call(userId, stream) // We Connect To Other User
    const video = document.createElement('video')
    call.on('stream', userVideoStream => { // Other User Connects To Us
        addVideoStream(video, userVideoStream)
    })
    call.on('close', () => { // Other User Disconnects
        video.remove()
    })

    peers[userId] = call
}

function addVideoStream(video, stream) {
    video.srcObject = stream
    video.addEventListener('loadedmetadata', () => {
        video.play()
    })
    videoGrid.append(video)
}

我是 nodejs 新手,在网上找不到任何解决方案。

请帮忙!!

【问题讨论】:

  • 显示文件层次结构和 SSL 证书来源。
  • 我们需要您的 room.ejs 文件来确定答案

标签: node.js express socket.io peerjs


【解决方案1】:

您的代码需要重新安排,一旦完成,它在 W10、VSC 和 Chrome 版本 91.0.4472.164(官方构建)(64 位)上运行良好。包含我的工作代码而不是试图解释每个更改更简单。我将在此处包含 script.js 和 server.js 文件(工作)以及 github here 中的整个代码工作区,供任何人使用。我想强调一下,您确实想在等待任何承诺之前调用 peer.on('call'.... 事件处理程序,以确保您的远程客户端在收到来自发起者客户端的呼叫之前准备好此处理程序,这不是造成您询问的错误的问题的一部分。

客户端:

const socket = io('/')
const videoGrid = document.getElementById('video-grid')
let Peer = window.Peer;
const peer = new Peer({
    host: '/',
    path: '/peerjs',
    debug: 3,
    port: 80,
    secure: false,
});

console.log('***Created peer instance, userId: ' + peer.id)

// Function to obtain stream and then await until after it is obtained to go into video chat call and answer code. Critical to start the event listener ahead of everything to ensure not to miss an incoming call.

const ownVideo = document.createElement('video') // Own Video
ownVideo.muted = true
const peers = {}
// On Receiving Other Persons Call
peer.on("call", async (call) => {
    try {
        let stream = null;
        stream = await navigator.mediaDevices.getUserMedia({
            video: true,
            audio: true
        });
        call.answer(stream) // Send Video Stream On Answer
        const video = document.createElement('video');
        // Send Back Video Stream On Stream
        call.on('stream', userVideoStream => {
            addVideoStream(video, userVideoStream);
        });
    }
    catch (err) {
        /* handle the error */
        console.log('*** ERROR returning the stream: ' + err);
    }
});

    (async () => {
        try {
            let stream = null;
            stream = await navigator.mediaDevices.getUserMedia(
                {
                    audio: true,
                    video: true,
                });
            if (stream != undefined) {
                addVideoStream(ownVideo, stream);
                console.log('added own Video stream');
            } else {
                console.log('You can only access your audio/video media streams over https');
                alert('Sorry retry using https, for security reasons Google Media blocks access to your video stream over unsecure http connections');
            }
        } catch (err) {
            /* handle the error */
            console.log('*** ERROR returning the stream: ' + err);
            alert('Sorry retry using https, for security reasons Google Media blocks access to your video stream over unsecure http connections');
        }
    })();


socket.on('user-connected', userId => { // Allow Self To Be Connected To Others
    console.log('User Connected: ' + userId)
    navigator.mediaDevices.getUserMedia({
        video: true,
        audio: true
    }).then(stream => {
        connectToNewUser(userId, stream)
    })
})

socket.on('user-disconnected', userId => {
    if (peers[userId]) peers[userId].close()
})

peer.on('open', id => {
    socket.emit('join-room', ROOM_ID, id)
})

function connectToNewUser(userId, stream) {
    const call = peer.call(userId, stream) // We Connect To Other User
    const video = document.createElement('video')
    call.on('stream', userVideoStream => { // Other User Connects To Us
        addVideoStream(video, userVideoStream)
    })
    call.on('close', () => { // Other User Disconnects
        video.remove()
    })

    peers[userId] = call
}

function addVideoStream(video, stream) {
    video.srcObject = stream
    video.addEventListener('loadedmetadata', () => {
        video.play()
    })
    videoGrid.append(video)
}

服务器端:

// Dependencies
const express = require('express')
const app = express()
const httpPort = process.env.PORT || 80
const httpsPort = 443
const { ExpressPeerServer } = require('peer')
const path = require('path')
const http = require('http')
const https = require('https')
const fs = require('fs')
const certs = `C:/Users/spine/Documents/Personal Files/ArduinoData/packages/esp8266/hardware/esp8266/2.7.4/libraries/ESP8266WiFi/examples/BearSSL_Server/`


// Certificate & credentials
const privateKey = fs.readFileSync(path.join(certs, 'key.pem'))
const certificate = fs.readFileSync(path.join(certs, 'cert.pem'))
const credentials = {
        key: privateKey,
        cert: certificate
}

const mainServer = http.createServer(app).listen(httpPort, () => { console.log('Main Server listening to port ' + httpPort) })
const httpsServer = https.createServer(credentials, app).listen(httpsPort, () => { console.log('Peer Server listening to port ' + httpsPort) })

const peerServer = ExpressPeerServer(mainServer, {
        debug: true,
        ssl: {},
})

app.use('/peerjs', peerServer)
// app.use(peerServer)

const io = require('socket.io')(httpsServer,{
// const io = require('socket.io')(mainServer, {
  cors: {
      origin: "*",
  },
});
const { v4: uuidV4 } = require('uuid')

app.set('view engine', 'ejs')
app.use(express.static('public'))

app.get('/', (req, res) => {
  res.redirect(`/${uuidV4()}`)
})

app.get('/:room', (req, res) => {
  res.render('room', { roomId: req.params.room })
  //console.log('Room Created / Joined')
})

io.on('connection', (socket) => {
    //console.log('IO Connectedd')
    socket.on('join-room', (roomId, userId) => {
        console.log(roomId, userId)
        socket.join(roomId)
        socket.to(roomId).emit('user-connected', userId)

        socket.on('disconnect', () => {
            socket.to(roomId).emit('user-disconnected', userId)
        })
    })
})

【讨论】:

  • 在端口 443 上使用安全 io 和安全对等体,它仍然有效,但它给出了一个错误( websocket.js:88 WebSocket connection to 'wss://localhost/socket.io/?EIO=4&transport =websocket&sid=6OZ-XkQLfVusmNW7AAAS' failed:) 在 wss 连接到 sockets.io 期间。我已在 peerjs 服务器 github 站点中将此问题报告为问题,这里是 link
  • 我让它以某种方式工作。不过,我仍然面临一些麻烦。你能帮我stackoverflow.com/questions/68472182/…
【解决方案2】:

我让它在服务器端使用以下 cod。虽然我只能通过 SSL 让它工作。

const express = require('express')
const app = express()
const httpPort = process.env.PORT || 80
const httpsPort = 443
const { ExpressPeerServer } = require('peer')
const path = require('path')
const http = require('http')
const https = require('https')
const fs = require('fs')

// Certificate & credentials
const privateKey = fs.readFileSync(path.join(__dirname, 'certs', 'key.pem'))
const certificate = fs.readFileSync(path.join(__dirname, 'certs', 'cert.pem'))
const credentials = {
    key: privateKey,
    cert: certificate
}

const httpsServer = https.createServer(credentials, app).listen(httpsPort, () => { console.log('Peer Server listening to port ' + httpsPort) })

const peerServer = ExpressPeerServer(httpsServer, {
        debug: true,
        path: '/myapp'
})

app.use(peerServer)

const io = require('socket.io')(httpsServer, {
   forceNew: true,
   transports: ["polling"],
})
const { v4: uuidV4 } = require('uuid')

app.set('view engine', 'ejs')
app.use(express.static('public'))

app.get('/', (req, res) => {
  res.redirect(`/${uuidV4()}`)
})

app.get('/:room', (req, res) => {
  res.render('room', { roomId: req.params.room })
})

io.on('connection', (socket) => {
    socket.on('join-room', (roomId, userId) => {
        socket.join(roomId)
        socket.broadcast.to(roomId).emit('user-connected', userId)

        socket.on('disconnect', () => {
            socket.broadcast.to(roomId).emit('user-disconnected', userId)
        })
        socket.on('text-message', message => {
            socket.broadcast.to(roomId).emit('text-message-received', message)
        })
        socket.on('system-stream-updated', remoteUserId => {
            socket.broadcast.to(roomId).emit('new-remote-stream', remoteUserId)
        })
    })
})

【讨论】:

  • 您的意思是我在上面的答案中发布的代码对您不起作用吗?它对我有用......我唯一的问题是 wss 中的套接字错误,但尽管如此仍然可以正常工作。
猜你喜欢
  • 2014-12-27
  • 1970-01-01
  • 2016-06-21
  • 2020-08-17
  • 1970-01-01
  • 2016-09-09
  • 2017-12-12
  • 2019-07-10
  • 2014-11-04
相关资源
最近更新 更多