WebSocket连接失败:WebSocket握手期间出错:意外的响应代码:400。

92

我试图将Socket.io与Angular集成,但是在客户端与服务器之间建立连接时遇到了困难。我查看了其他相关问题,但我的问题发生在本地,所以中间没有Web服务器。

这是我的服务器代码:

const app = express();
const server = http.createServer(app);
const io = require('socket.io').listen(server);

io.on('connection', function(socket) {
  socket.emit('greet', { hello: 'Hey, Mr.Client!' });

  socket.on('respond', function(data) {
    console.log(data);
  });
  socket.on('disconnect', function() {
    console.log('Socket disconnected');
  });
});

我正在使用Grunt按照以下顺序加载客户端JavaScript文件:

dist: {
    src: [
        public/bower_components/angular/angular.min.js,
        ...
        public/bower_components/socket.io-client/dist/socket.io.min.js,
        public/bower_components/angular-socket-io/socket.min.js,
        ...
    ]
}

然后在我的控制器中:

function MyController($scope) {

    let socket = io.connect(window.location.href);
    socket.connect('http://localhost:3000');
    socket.on('greet', function(data) {
      console.log(data);
      socket.emit('respond', { message: 'Hello to you too, Mr.Server!' });
    });

    ...
}

在实际使用btford/angular-socket-io库之前,我想确保可以正确连接,但是控制台中出现以下错误:

socket io connection error message

有趣的是,如果重新启动Node.js服务器进程,则可以发送消息,但是使用轮询而不是WebSockets。

after restart

polling message

我尝试了各种不同的选项来调用socket.connect,但没有任何作用。

感激任何帮助。


更新(2016年12月30日):

我刚刚意识到WebSockets部分工作。在Chrome开发者控制台中看到了101切换协议请求。但是,我只能看到那里的engine.io协议数据包(ping,pong)。 但是我的应用程序套接字消息仍然因某种原因回退到轮询...

engine.io packets


5
你是否使用nginx作为代理服务器? - digit
嘿,数字,目前还没有Web服务器。我读到了必须设置升级标头才能使其工作,但我目前只是在本地开发。 - ashe540
我在使用Pusher和Laravel时遇到了问题。我不知道为什么,但是我收到了这个错误:(( - ali Falahati
22个回答

1
我在使用Node.js和Socket.IO时遇到了同样的错误,但原因非常愚蠢。并没有正确安装所有Socket.IO的依赖项,具体来说是缺少了base64id包。

1
您正在客户端使用3000端口。我猜测那是Angular端口而不是服务器端口?它应该连接到服务器端口。

1
如果您尝试了上面提供的每个选项,那么您的代码没有问题,请尝试停止浏览器的广告拦截器。这对我起作用了。 禁用拦截器后我的输出 输出 我的服务器 服务器

1

对我来说,问题不在于从process.env.PORT获取端口,因为Heroku和其他服务通常会使用随机端口号。

所以这是最终适合我的代码:

var app = require('express')();
var http = require('http').createServer(app);
const serverPort = process.env.PORT ; //<----- important 

const io = require('socket.io')(http,{
  cors: {
    origin: '*',
    methods: 'GET,PUT,POST,DELETE,OPTIONS'.split(','),
    credentials: true
  }
});

http.listen(serverPort,()=>{
  console.log(`server listening on port ${serverPort}`)
})

1

包括 transports: ['websocket'] 不是最佳方法,因为它会使 Socket.io 功能无法适用于任何场景。

在我的情况下,使用 Nodejs + Nginx + Vuejs/Vite(Front) ,我通过在 Nginx 的站点配置中配置反向代理来解决了这个问题。

http {
  server {
    listen 80;
    root /var/www/html;

    // <---- start ---->
    location /socket.io/ { // <--- Set your custom path
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $host;

      proxy_pass http://localhost:3000; // <--- Set your Port

      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
    }
    // <---- End ---->

  }
}

您可以在 Socket.io 网站或 Nginx 上找到有关此问题的参考资料。


1
如果您正在使用Flask、Gunicorn和Nginx作为反向代理,仅在使用socket.io的端点下配置这些选项是不够的。
我的意思是,假设您已经配置了一个名为'/chat'的端点,如下所示:
location /chat/ {
    proxy_pass http://backend;
    # Enable websockets
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

在我做了这个之后,我仍然不断遇到错误:WebSocket connection to 'ws://x.x.x.x/socket.io/?EIO=4&transport=websocket&sid=LNcNgeauE7z6dYBiAAAK' failed: Error during WebSocket handshake: Unexpected response code: 200
为了解决这个问题,我在我的配置文件中添加了另一个端点。
location /socket.io/ { 
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_set_header Host $host;

     proxy_pass http://localhost:3000; # Remember to change to your configured port

     proxy_http_version 1.1;
     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection "upgrade";
}

添加和配置了这个端点之后,我没有遇到任何ws错误。
更多参考资料:http://nginx.org/en/docs/http/websocket.html

0

使用以下负载均衡器设置后,我的wss问题得到了解决,但对于特定的一个ISP,ws问题仍然存在。

经典负载均衡器


0

我通过删除 io.listen(server); 解决了这个问题。当我开始集成 passport.socketio 并使用 passport 中间件时,我遇到了这个错误。


0

0

我的问题是在服务器端

const app = require("express")();
const http = require("http").Server(app);
const io = require("socket.io")(http);

使用

http.listen(PORT,()=> console.log('listening'))

当我执行时它给了我一个错误。

app.listen(......)

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