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

Posted

技术标签:

【中文标题】与“ws://localhost:3000/”的 WebSocket 连接失败:在收到握手响应之前连接已关闭【英文标题】:WebSocket connection to 'ws://localhost:3000/' failed: Connection closed before receiving a handshake response 【发布时间】:2017-12-12 04:09:39 【问题描述】:

我拿了一个朋友制作的游戏,并希望通过使用 WebRTC 和 websockets 在对等点之间发送按键数据来使其可以跨浏览器玩。但是,我在控制台中收到此错误:

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

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

'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】:

困惑从这里开始:

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 );

【讨论】:

谢谢,我没有意识到它是这样工作的,我一定会牢记命名约定。现在,击键正在发送画布元素,在“坦克”移动后绘制混乱。你帮了大忙!

以上是关于与“ws://localhost:3000/”的 WebSocket 连接失败:在收到握手响应之前连接已关闭的主要内容,如果未能解决你的问题,请参考以下文章

14.6 socket跨域

简单的多人聊天室

简单的多人聊天室

什么是 WebSocket 子协议?

如何使用 websocket 在具有相同令牌的用户之间发送消息?

=与==&与&&| 与 || 的区别