WebSocket-Verbindung fehlgeschlagen: Fehler beim WebSocket-Handshake: Unerwarteter Antwortcode: 400

Lesezeit: 9 Minuten

Benutzer-Avatar
Asche540

Ich versuche, Socket.io mit Angular zu integrieren, und ich habe Schwierigkeiten, eine Verbindung von der Clientseite zum Server herzustellen. Ich habe andere verwandte Fragen durchgesehen, aber mein Problem tritt lokal auf, daher gibt es keinen Webserver in der Mitte.

So sieht mein Servercode aus:

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

Ich lade die clientseitigen JavaScript-Dateien mit Grunt in der folgenden Reihenfolge:

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,
        ...
    ]
}

Dann in meinem Controller:

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!' });
    });

    ...
}

Vor der eigentlichen Verwendung der btford/angular-socket-io Bibliothek möchte ich sicherstellen, dass ich eine korrekte Verbindung herstellen kann, aber ich erhalte die folgende Fehlermeldung in der Konsole:

Socket io-Verbindungsfehlermeldung

Das Interessante ist, dass, wenn ich den Node.js-Serverprozess neu starte, er es schafft, die Nachricht zu senden, aber Polling anstelle von Websockets verwendet.

nach Neustart

Abfragenachricht

Ich habe alle möglichen Optionen im Socket.connect-Aufruf ausprobiert, aber nichts hat funktioniert.

Jede Hilfe wäre willkommen.


UPDATE (30.12.2016):

Ich habe gerade festgestellt, dass Websockets teilweise funktioniert. Ich sehe eine 101 Switching Protocols-Anforderung in der Chrome-Entwicklerkonsole. Die einzigen Frames, die ich dort sehe, sind jedoch die engine.io-Protokollpakete (Ping, Pong). Meine Anwendungs-Socket-Nachrichten fallen jedoch aus irgendeinem Grund immer noch auf die Abfrage zurück …

engine.io-Pakete

  • Benutzt du nginx als Proxyserver?

    – Ziffer

    29. Dezember 2016 um 14:29 Uhr

  • Hey Ziffer, nein, noch keine Webserver. Ich habe gelesen, dass der Upgrade-Header gesetzt werden muss, damit es funktioniert, aber ich entwickle im Moment nur lokal.

    – Asche540

    29. Dezember 2016 um 22:22 Uhr

  • Ich habe dieses Problem mit Pusher und Laravel. Ich weiß nicht warum, aber ich bekomme diesen Fehler :((

    – Ali Falahati

    31. Juli 2020 um 10:51 Uhr

Problem gelöst! Ich habe gerade herausgefunden, wie ich das Problem lösen kann, aber ich würde trotzdem gerne wissen, ob dies ein normales Verhalten ist oder nicht.

Es scheint, dass, obwohl die Websocket-Verbindung korrekt hergestellt wird (angezeigt durch die 101 Switching Protocols-Anforderung), immer noch standardmäßig Long-Polling verwendet wird. Die Lösung war so einfach wie das Hinzufügen dieser Option zur Socket.io-Verbindungsfunktion:

{transports: ['websocket']}

Der Code sieht also letztendlich so aus:

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

io.on('connection', function(socket) {
  console.log('connected socket!');

  socket.on('greet', function(data) {
    console.log(data);
    socket.emit('respond', { hello: 'Hey, Mr.Client!' });
  });
  socket.on('disconnect', function() {
    console.log('Socket disconnected');
  });
});

und auf dem Client:

var socket = io('ws://localhost:3000', {transports: ['websocket']});
socket.on('connect', function () {
  console.log('connected!');
  socket.emit('greet', { message: 'Hello Mr.Server!' });
});

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

Und die Nachrichten erscheinen jetzt als Rahmen:

funktionierende Websockets

Dies Github-Problem wies mich in die richtige Richtung. Danke an alle, die mitgeholfen haben!

  • Wie hast du Chrom dazu gebracht, die Rahmen so zu zeigen? Wenn ich auf eine sockIO-Anfrage klicke, wird keine Registerkarte für Frames angezeigt

    – kiwicomb123

    17. Mai 2018 um 23:25 Uhr


  • Wenn der Browser die Verbindung initiiert, sendet er eine Upgrade-Anfrage, auf die der Server mit einem 101-Switching-Protokoll antwortet. Sie müssen sicherstellen, dass Sie auf der Registerkarte Netzwerk nach dieser Anfrage suchen, da sie die Frames anzeigt, die zwischen den beiden Entitäten gesendet werden.

    – Asche540

    19. Mai 2018 um 0:27 Uhr

  • Ja, ich habe dorthin navigiert. Es gibt mehrere Fälle, in denen die Registerkarte “Frames” nicht auf der Registerkarte “Netzwerk” vorhanden ist.

    – kiwicomb123

    19. Mai 2018 um 0:29 Uhr

  • Danke, das hat bei mir funktioniert, hatte das gleiche Problem wie OP

    – Ryan Rebo

    7. Februar 2020 um 1:49 Uhr

  • Beachten Sie, dass durch das Hinzufügen dieser Option das Long-Polling-Fallback effektiv entfernt wird, was einer der Gründe ist socket.io ist in erster Linie so robust. Sehen https://socket.io/docs/using-multiple-nodes/.

    – Kathandrax

    28. März 2020 um 13:52 Uhr

Das hat bei mir mit Nginx, Nodeserver und Angular 4 funktioniert

Bearbeiten Sie Ihre Nginx-Webserver-Konfigurationsdatei wie folgt:

server {
listen 80;
server_name 52.xx.xxx.xx;

location / {
    proxy_set_header   X-Forwarded-For $remote_addr;
    proxy_set_header   Host $http_host;
    proxy_pass         "http://127.0.0.1:4200";
    proxy_http_version 1.1;
    proxy_set_header   Upgrade $http_upgrade;
    proxy_set_header   Connection "upgrade";
}

  • Obwohl das OP nach einem lokalen Problem fragt, bei dem kein nginx-Reverse-Proxy beteiligt ist, ist diese Antwort die richtige nginx-Einstellung, wenn sie im Spiel ist

    – Scott Stensland

    6. Februar 2018 um 15:13 Uhr

  • Das Hinzufügen der Upgrade-Header für meine Konfiguration war das, was ich brauchte. proxy_http_version 1.1; hat dazu geführt, dass der Nginx-Dienst nicht gestartet werden konnte.

    – JDavis

    6. März 2018 um 23:31 Uhr

  • Für diejenigen, die weitere Informationen zur Verwaltung von Nginx-Headern wünschen: digitalocean.com/community/tutorials/…

    – JoshuaTree

    14. März 2018 um 5:13 Uhr

  • Und für diejenigen, die wissen wollen, warum der Upgrade-Header? nginx.com/blog/websocket-nginx

    – JoshuaTree

    14. März 2018 um 5:15 Uhr

  • Bei mir fehlten die letzten beiden Zeilen für das Upgrade.

    – Cybersupernova

    17. September 2019 um 18:25 Uhr

Benutzer-Avatar
Kathandrax

Die derzeit akzeptierte Lösung ist irreführend.

Laut dem amtliche DokumentationHinzufügen der transports: [ 'websocket' ] Option entfernt effektiv die Möglichkeit, auf Long-Polling zurückzugreifen, wenn die Websocket-Verbindung nicht hergestellt werden kann. Diese Option macht socket.io in erster Linie so robust, weil es sich an viele Szenarien anpassen kann.

In dem speziellen Fall, in dem man sich ausschließlich auf Websockets verlassen möchte, direkt über die WebSocket API ist empfohlen.

In anderen Fällen (angeblich die meisten Benutzer) ist dies höchstwahrscheinlich ein Problem mit der Reverse-Proxy-/Serverkonfiguration.

Die offizielle Dokumentation schlägt abhängig von Ihrer Umgebung Folgendes vor:

NginX-Konfiguration

http {
  server {
    listen 3000;
    server_name io.yourhost.com;

    location / {
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $host;

      proxy_pass http://nodes;

      # enable WebSockets
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
    }
  }

  upstream nodes {
    # enable sticky session based on IP
    ip_hash;

    server app01:3000;
    server app02:3000;
    server app03:3000;
  }
}

Apache HTTPD-Konfiguration

Header add Set-Cookie "SERVERID=sticky.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED

<Proxy "balancer://nodes_polling">
    BalancerMember "http://app01:3000" route=app01
    BalancerMember "http://app02:3000" route=app02
    BalancerMember "http://app03:3000" route=app03
    ProxySet stickysession=SERVERID
</Proxy>

<Proxy "balancer://nodes_ws">
    BalancerMember "ws://app01:3000" route=app01
    BalancerMember "ws://app02:3000" route=app02
    BalancerMember "ws://app03:3000" route=app03
    ProxySet stickysession=SERVERID
</Proxy>

RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) balancer://nodes_ws/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule /(.*) balancer://nodes_polling/$1 [P,L]

ProxyTimeout 3

HAProxy-Konfiguration

listen chat
  bind *:80
  default_backend nodes

backend nodes
  option httpchk HEAD /health
  http-check expect status 200
  cookie io prefix indirect nocache # using the `io` cookie set upon handshake
  server app01 app01:3000 check cookie app01
  server app02 app02:3000 check cookie app02
  server app03 app03:3000 check cookie app03

Auch lesenswert Dies beim Aktualisieren von Verbindungen in HAProxy.

Weitere Einzelheiten finden Sie unter dem Link zur offiziellen Dokumentation oben.

BEARBEITEN:

Lack (Quelle hier)

sub vcl_recv {
    if (req.http.upgrade ~ "(?i)websocket") {
        return (pipe);
    }
}

sub vcl_pipe {
    if (req.http.upgrade) {
        set bereq.http.upgrade = req.http.upgrade;
        set bereq.http.connection = req.http.connection;
    }
}

  • Das Upgrade meiner Websocket-Verbindung schlägt fehl. Weiß nicht warum. Ich habe diese Konfiguration für Nginx location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwared-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; proxy_pass http://127.0.0.1:3000; proxy_redirect off; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; client_max_body_size 100M; }

    – Anbieter

    2. Juli 2020 um 19:33 Uhr


  • Entschuldigung für die späte Antwort @invider @Norbert. Hast du dein Problem behoben? Ich sehe, da ist ein Tippfehler drin proxy_set_header X-Forwared-For $proxy_add_x_forwarded_for; – es sollte sein X-Forwarded-For. Haben Sie auch überprüft, ob Ihr Proxy_pass-Ziel erreichbar ist (und insbesondere über Port 3000)?

    – Kathandrax

    18. Juni 2021 um 14:48 Uhr

  • Erinnere mich eigentlich nicht

    – Anbieter

    19. Juni 2021 um 8:53 Uhr

Ich habe dies gelöst, indem ich die Transporte von „websocket“ auf „polling“ geändert habe.

   var socket = io.connect('xxx.xxx.xxx.xxx:8000', {
      transports: ['polling']
   });

Benutzer-Avatar
Kuriakin Zeng

Gemessen an den Nachrichten, die Sie über Socket.IO senden socket.emit('greet', { hello: 'Hey, Mr.Client!' });es scheint, dass Sie die verwenden hackathon-starter Kesselplatte. Wenn ja, könnte das Problem daran liegen express-status-monitor Modul erstellt seine eigene socket.io-Instanz, wie folgt: https://github.com/RafalWilinski/express-status-monitor#using-module-with-socketio-in-project

Du kannst entweder:

  1. Entfernen Sie dieses Modul
  2. Übergeben Sie Ihre socket.io-Instanz und den Port als websocket wenn Sie die erstellen expressStatusMonitor Beispiel wie unten:

    const server = require('http').Server(app);
    const io = require('socket.io')(server);
    ...
    app.use(expressStatusMonitor({ websocket: io, port: app.get('port') })); 
    

  • Super! Vielen Dank!

    – Marco Burrometo

    25. Januar 2020 um 19:06 Uhr

Benutzer-Avatar
Hitesh Subnani

Hatte das gleiche Problem, meine App ist hinter nginx. Durch diese Änderungen an meiner Nginx-Konfiguration wurde der Fehler behoben.

location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}

  • Super! Vielen Dank!

    – Marco Burrometo

    25. Januar 2020 um 19:06 Uhr

Benutzer-Avatar
Tejas-Panzer

Ich hatte die gleichen Probleme, ich verfeinerte die Eingabe des virtuellen Apache2-Hosts und hatte Erfolg.

Hinweis: Auf dem Server hatte ich erfolgreich den Port 9001 installiert und funktionierte ohne Probleme. Diese Richtlinie für Apache2 nur keine Relevanz mit nginx, diese Antwort für Liebhaber von Apache2 + Etherpad.

<VirtualHost *:80>
  ServerName pad.tejastank.com
  ServerAlias pad.tejastank.com
  ServerAdmin [email protected]

  LoadModule  proxy_module         /usr/lib/apache2/modules/mod_proxy.so
  LoadModule  proxy_http_module    /usr/lib/apache2/modules/mod_proxy_http.so
  LoadModule  headers_module       /usr/lib/apache2/modules/mod_headers.so
  LoadModule  deflate_module       /usr/lib/apache2/modules/mod_deflate.so

  ProxyVia On
  ProxyRequests Off
  ProxyPreserveHost on

    <Location />
        ProxyPass http://localhost:9001/ retry=0 timeout=30
        ProxyPassReverse http://localhost:9001/
    </Location>
    <Location /socket.io>
        # This is needed to handle the websocket transport through the proxy, since
        # etherpad does not use a specific sub-folder, such as /ws/ to handle this kind of traffic.
        # Taken from https://github.com/ether/etherpad-lite/issues/2318#issuecomment-63548542
        # Thanks to beaugunderson for the semantics
        RewriteEngine On
        RewriteCond %{QUERY_STRING} transport=websocket    [NC]
        RewriteRule /(.*) ws://localhost:9001/socket.io/$1 [P,L]
        ProxyPass http://localhost:9001/socket.io retry=0 timeout=30
        ProxyPassReverse http://localhost:9001/socket.io
    </Location>


  <Proxy *>
    Options FollowSymLinks MultiViews
    AllowOverride All
    Order allow,deny
    allow from all
  </Proxy>
</VirtualHost>

Vorab-Tipps: Bitte aktivieren Sie mit Hilfe von a2enmod alle Mods von Apache2

Starten Sie Apache2 neu, um die Wirkung zu erzielen. Aber offensichtlich a2ensite zum Aktivieren der Website erforderlich.

  • Ich habe alle deine geändert http:// zu https:// und ws:// zu wss:// — funktioniert gut. vielen Dank, dass du das geteilt hast. Die Verwendung von localhost:### in diesem Zusammenhang ist sehr interessant, das habe ich noch nie gesehen.

    – Edwardsmarkf

    15. Januar 2019 um 23:12 Uhr


  • Ja, das hat bei mir funktioniert. Vielen Dank. Die Rewrite-Regeln waren vielleicht das Problem für mich

    – Devender Gupta

    1. Oktober 2020 um 12:20 Uhr


  • Das hat bei mir funktioniert – die <Location /socket.io> Ich habe meine Einstellungen nicht darin eingeschlossen … aber ja, hat sehr geholfen. Danke Alter!

    – Robert

    12. November 2020 um 23:41 Uhr

  • Ursache: Fehler beim SSL-Handshake mit Remote-Server

    – Nie wieder

    8. März 2021 um 11:16 Uhr

1125900cookie-checkWebSocket-Verbindung fehlgeschlagen: Fehler beim WebSocket-Handshake: Unerwarteter Antwortcode: 400

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy