WebSocket连接到'ws://localhost:3000/'失败:在接收握手响应之前关闭连接。

11

我拿到了一个朋友制作的游戏,并希望通过在同行之间发送键盘数据来使其适用于各种浏览器,使用的是WebRTC和Websockets。但是,在控制台中我看到了以下错误信息:

WebSocket连接到'ws:// localhost:3000 /'失败:在接收握手响应之前已关闭连接

我的服务器文件有以下几行代码:

'use strict';

const express = require('express');
const SocketServer = require('ws').Server;
const path = require('path');

const PORT = process.env.PORT || 3000;
const INDEX = path.join(__dirname, 'index.html');

const server = express();

server.use(express.static(path.join(__dirname, 'lib')));
server.use('/assets', express.static(path.join(__dirname, 'assets')));
server.listen(PORT, () => console.log(`Listening on ${ PORT }`));

const wss = new SocketServer({ server });
var users = {};
let usernames = [];


wss.on('connection', function(connection) {

   connection.on('message', function(message) {

      var data;
      try {
         data = JSON.parse(message);
      } catch (e) {
         console.log("Invalid JSON");
         data = {};
      }

      switch (data.type) {
         case "login":
            console.log("User logged", data.name);
            if(users[data.name]) {
               sendTo(connection, {
                  type: "login",
                  success: false
               });
            } else {
               users[data.name] = connection;
               connection.name = data.name;
               usernames.push(data.name);

               sendTo(connection, {
                  type: "login",
                  success: true,
                  users: usernames
               });
            }

            break;

         case "offer":
            console.log("Sending offer to: ", data.name);
            var conn = users[data.name];

            if(conn != null) {
               connection.otherName = data.name;

               sendTo(conn, {
                  type: "offer",
                  offer: data.offer,
                  name: connection.name
               });
            }

            break;

         case "answer":
            console.log("Sending answer to: ", data.name);
            var conn = users[data.name];

            if(conn != null) {
               connection.otherName = data.name;
               sendTo(conn, {
                  type: "answer",
                  answer: data.answer
               });
            }

            break;

         case "candidate":
            console.log("Sending candidate to:",data.name);
            var conn = users[data.name];

            if(conn != null) {
               sendTo(conn, {
                  type: "candidate",
                  candidate: data.candidate
               });
            }

            break;

         case "leave":
            console.log("Disconnecting from", data.name);
            var conn = users[data.name];
            conn.otherName = null;

            if(conn != null) {
               sendTo(conn, {
                  type: "leave"
               });
            }

            break;

         default:
            sendTo(connection, {
               type: "error",
               message: "Command not found: " + data.type
            });

            break;
      }
   });

客户端连接的代码如下:

const Game = require("./game");
const GameView = require("./game_view");
var HOST = location.origin.replace(/^http/, 'ws');
console.log('host: ', HOST);
console.log(process.env.PORT);

document.addEventListener("DOMContentLoaded", function() {
  const connection = new WebSocket(HOST);

.....

出错的位置是这里,下面是我捕获到的错误信息:

bubbles
:
false
cancelBubble
:
false
cancelable
:
false
composed
:
false
currentTarget
:
WebSocket
defaultPrevented
:
false
eventPhase
:
0
isTrusted
:
true
path
:
Array(0)
returnValue
:
true
srcElement
:
WebSocket
target
:
WebSocket
timeStamp
:
213.01500000000001
type
:
"error"
__proto__
:
Event

我对服务器端编程不太熟悉,正在努力理解。我试图查找此问题,但似乎有各种不同的原因可以导致这种情况。如果您想查看存储库并自行尝试(使用webpack):SlidingWarfare Repo

1个回答

16

混乱从这里开始:

const server = express();

express 函数并不返回一个服务器,它返回一个应用程序。通常情况下,用于此目的的变量是 app,但这当然只是惯例(即不是必需的)。

但是,当您将应用程序传递给 WS 服务器时,这就成为了一个问题:

const wss = new SocketServer({ server });

这是因为SocketServer需要一个HTTP服务器实例,而server并不属于它。

以下是一种修复方式,而不需要重命名你的变量:

let httpServer = server.listen(PORT, () => console.log(`Listening on ${ PORT }`));
...
const wss = new SocketServer({ server : httpServer });

(因为当您在 Express 实例上调用 .listen() 时,它将返回一个 HTTP 服务器实例)

使用变量命名约定,它将是这样的:

const app = express();

app.use(express.static(path.join(__dirname, 'lib')));
app.use('/assets', express.static(path.join(__dirname, 'assets')));

let server = app.listen(PORT, () => console.log(`Listening on ${ PORT }`));

const wss = new SocketServer({ server });

1
谢谢,我没有意识到它是这样工作的,我一定会记住命名规范。现在按键发送后,"坦克"移动后画布元素会出现问题。你非常有帮助! - Yasin Hosseinpur
伙计,我花了数小时的时间才解决这个问题,真是让我抓狂。但是这个答案解决了很多问题。非常感谢你提供的答案! - Alex Navarro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接