programing

WebSocket 연결 실패:WebSocket 핸드쉐이크 중 오류 발생:예기치 않은 응답 코드: 400

css3 2023. 3. 21. 22:25

WebSocket 연결 실패:WebSocket 핸드쉐이크 중 오류 발생:예기치 않은 응답 코드: 400

Socket.io을 Angular와 통합하려고 하는데 클라이언트 측에서 서버로의 접속에 어려움을 겪고 있습니다.관련된 다른 질문들을 살펴보았지만, 제 문제는 로컬에서 발생하고 있기 때문에 중간에 웹 서버가 없습니다.

서버 코드는 다음과 같습니다.

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라이브러리, 올바르게 접속할 수 있는지 확인하고 싶은데 콘솔에 다음 오류가 나타납니다.

소켓 IO 연결 오류 메시지

흥미로운 점은 Node.js 서버 프로세스를 재시작하면 메시지를 보낼 수 있지만 웹소켓 대신 폴링을 사용한다는 것입니다.

재기동 후

폴링 메시지

socket.connect 호출로 여러 가지 옵션을 시도해 봤지만 아무 소용이 없었습니다.

어떤 도움이라도 주시면 감사하겠습니다.


업데이트 (2016년 12월 30일) :

웹소켓이 부분적으로 작동하고 있다는 것을 방금 알았습니다.Chrome 개발자 콘솔에 101 Switching Protocols 요청이 표시됩니다.다만, 표시되는 프레임은 engine.io 의 프로토콜 패킷(ping, pong) 뿐입니다.단, 어플리케이션소켓 메시지는 어떤 이유로 폴링에 반환됩니다.

engine.io 패킷

문제 해결!저는 방금 문제를 해결하는 방법을 알아냈지만, 이것이 정상적인 행동인지 알고 싶습니다.

(101 스위칭 프로토콜 요청으로 표시됨) 웹 소켓 연결이 올바르게 설정되더라도 기본값이 롱 폴링인 것으로 보입니다.이 수정은 Socket.io 연결 함수에 이 옵션을 추가하는 것만으로 간단합니다.

{transports: ['websocket']}

마지막으로 코드는 다음과 같습니다.

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

및 클라이언트:

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

이제 메시지는 프레임으로 표시됩니다.

동작하는 웹소켓

Github 문제는 나에게 올바른 방향을 제시해 주었다.도와주신 모든 분들께 감사드립니다!

Nginx, Node 서버 및 Angular 4에서 작동했습니다.

nginx 웹 서버 구성 파일을 다음과 같이 편집합니다.

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";
}

현재 받아들여지고 있는 솔루션은 오해를 불러일으키고 있습니다.

공식 설명서에 따르면,transports: [ 'websocket' ]옵션을 사용하면 웹 소켓 연결을 확립할 수 없을 때 롱 소켓으로 폴백하는 기능을 효과적으로 제거할 수 있습니다., 「」가 됩니다.socket.io많은 시나리오에 적응할 수 있기 때문에 애초에 매우 강력합니다.

특히 웹소켓에만 의존하는 경우에는 를 직접 사용하는 것이 좋습니다.

그 외의 경우(대부분의 유저로 추정)에서는, 이것은 역프록시/서버 설정의 문제일 가능성이 높습니다.

공식 문서에서는 환경에 따라 다음 사항을 제안합니다.

NginX 설정

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 구성

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 설정

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

HAProxy의 접속 업그레이드에서도 읽을 수 있습니다.

자세한 내용은 위의 공식 문서 링크를 참조하십시오.

편집:

바니시(출처: 여기)

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

이 문제를 해결하기 위해 트랜스포트를 '웹소켓'에서 '폴링'으로 변경했습니다.

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

소켓을 통해 보내는 메시지로 판단하건대. ★★★★socket.emit('greet', { hello: 'Hey, Mr.Client!' });하시는 것 hackathon-starter그렇다면 문제가 될 수 .express-status-monitor모듈이 자체 socket.io 인스턴스를 만들고 있습니다.https://github.com/RafalWilinski/express-status-monitor#using-module-with-socketio-in-project

다음 중 하나를 수행할 수 있습니다.

  1. 모듈을 분리합니다.
  2. io 및를 socket.io로 합니다.websocket를 했을 때expressStatusMonitor다음과 같이 합니다.

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

같은 문제였지만 내 앱은 nginx보다 늦었다.Nginx 설정을 변경함으로써 오류가 삭제되었습니다.

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

저는 같은 문제에 직면하여 apache2 가상 호스트 Entery를 개량하여 성공을 거두었습니다.

주의: 서버에서는 9001 포트로 문제없이 정상적으로 설치 및 동작하고 있습니다.이 apache2 전용 가이드라인은 nginx와 관계가 없습니다.이 답변은 apache2+etherpad 애호가에게만 해당됩니다.

<VirtualHost *:80>
  ServerName pad.tejastank.com
  ServerAlias pad.tejastank.com
  ServerAdmin snippetbucket@gmail.com

  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>

어드밴스 힌트:a2enmod의 도움을 받아 apache2의 모든 모드를 활성화하십시오.

apache2 를 재기동합니다.하지만 사이트를 활성화하려면 명백한 a2ensite가 필요합니다.

""를 .http이 좋을 것 .ws이치노 써보세요.ws://localhost:3000사용할 수 있습니다.

는 네가 의 이름을 해.origins다음 중 하나:

//server.js
const socket = require('socket.io');
const app = require('express')();
const server = app.listen('port');

const io = socket().attach(server);
io.origins("your_domain:port www.your_domain:port your_IP:port your_domain:*")

io.on('connection', (socket) => {
  console.log('connected a new client');
});

//client.js
var socket = io('ws://:port');

이 에러를 해소하기 위해서 express-status-monitor 를 인스톨 했을 뿐입니다.

다음은 설정입니다.

install express-status-monitor
npm i express-status-monitor --save
const expressStatusMonitor = require('express-status-monitor');
app.use(expressStatusMonitor({
    websocket: io,
    port: app.get('port')
}));

는, 하지 않은 입니다.process.env.PORTHeroku와 다른 서비스들이 사용하는 임의의 포트 번호를 적절하게 처리하기 때문에 매우 중요합니다.

그래서 그것이 나에게 효과가 있는 코드입니다.

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}`)
})

node.witk socket.io 에서 같은 에러가 발생했지만, 그 이유는 매우 어리석었습니다.socket.io의 모든 종속성이 올바르게 설치되어 있지 않습니다.즉, 패키지 base64id가 누락되었습니다.

클라이언트 측에서 포트 3000을 사용하고 있습니다.서버 포트가 아니라 앵귤러 포트인 것 같은데?서버 포트에 연결되어 있어야 합니다.

다음 로드 밸런서 설정을 사용해도 특정 ISP에 대해 wss에 대해 문제가 해결되었지만 ws에 대해서는 문제가 여전히 존재합니다.

calsic-load-modered의

이 문제를 해결하려면io.listen(server);passport.socketio를 통합하고 여권 미들웨어를 사용할 때 이 오류가 발생하기 시작했습니다.

httpd/http를 사용하는 경우 ws.conf와 같은 파일을 추가하여 이 코드를 추가할 수 있습니다.또, 이 솔루션에서는, 「http://localhost:6001/socket.io」와 같은 것을 「http://localhost/socket.io」에 프록시 할 수 있습니다.

<VirtualHost *:80>
    RewriteEngine on

    #redirect WebSocket
    RewriteCond %{REQUEST_URI}  ^/socket.io            [NC]
    RewriteCond %{QUERY_STRING} transport=websocket    [NC]
    RewriteRule /(.*)           ws://localhost:6001/$1 [P,L]

    ProxyPass        /socket.io http://localhost:6001/socket.io
    ProxyPassReverse /socket.io http://localhost:6001/socket.io
</VirtualHost>

Apollo Server 2 사용.

https://github.com/apollographql/apollo-client/issues/4778#issuecomment-509638071,에 따르면, 이것으로 문제가 해결되었습니다.

'ws://localhost:syslog/graphql' 시도

...착신 요구와 발신 요구가 같은 주소를 사용하게 되었기 때문입니다.

나의 문제는 서버 쪽이었다.

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

귀를 기울이다

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

내가 했을 때 그것은 나에게 오류를 주었다.

app.listen(......)

포함하여transports: ['websocket']는, 어떠한 시나리오에서도 Sockt.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에서 찾을 수 있습니다.

위의 모든 옵션을 시도했다면 코드에는 문제가 없습니다.브라우저의 애드 블로커를 정지해 주세요.그것은 나에게 효과가 있었다.

블로커를 비활성화한 후 마이 출력 산출량

내 서버 서버

언급URL : https://stackoverflow.com/questions/41381444/websocket-connection-failed-error-during-websocket-handshake-unexpected-respon