Ошибка подключения WebSocket: ошибка при рукопожатии WebSocket: непредвиденный код ответа: 400
Я пытаюсь интегрировать сокет.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');
});
});
я загружаю файлы JavaScript на стороне клиента с помощью Grunt в следующем порядке:
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
библиотека, я хочу убедиться, что я могу получить соединение правильно, но я получаю следующую ошибку в консоли:
интересно то, что если я перезапущу узел.процесс сервера js, ему удается отправить сообщение, но используя опрос вместо websockets.
Я пробовал все виды различных опций в сокете.connect call, но ничего не сработало.
любая помощь будет оценили.
обновление (30/12/2016):
Я только что понял, что websockets работает частично. Я вижу 101 запрос протоколов переключения в консоли разработчика Chrome. Однако только кадров я вижу есть двигатель.пакеты протокола ввода-вывода (ping, pong). Однако мои сообщения сокета приложения по-прежнему возвращаются к опросу по какой-то причине...
6 ответов
проблема решена! Я только что понял, как решить проблему, но я все равно хотел бы знать, является ли это нормальным поведением или нет.
кажется, что, хотя соединение Websocket устанавливается правильно (указано запросом 101 протокола переключения), оно по-прежнему по умолчанию имеет длинный опрос. Исправление было так же просто, как добавление этой опции в сокет.функция подключения 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 указал мне в правильном направлении. Спасибо всем, кто помог!
судя по сообщениям, которые вы отправляете через сокет.IO socket.emit('greet', { hello: 'Hey, Mr.Client!' });
похоже, что вы используете hackathon-starter
boilerplate. Если это так, проблема может быть в том, что express-status-monitor
модуль создает свой собственный сокет.экземпляр io, согласно: https://github.com/RafalWilinski/express-status-monitor#using-module-with-socketio-in-project
вы можете:
- удалить модуль
-
Pass в вашем гнезде.экземпляр io и порт as
websocket
когда вы создайтеexpressStatusMonitor
экземпляра, как показано ниже:const server = require('http').Server(app); const io = require('socket.io')(server); ... app.use(expressStatusMonitor({ websocket: io, port: app.get('port') }));
это сработало для меня с Nginx, Node server и 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";
}
в вашем контроллере вы используете http
схему, но я думаю, что вы должны использовать ws
схема, так как вы используете websockets. Попробуйте использовать ws://localhost:3000
в функции Connect.
Я думаю, вы должны определить свой 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');
я столкнулся с теми же проблемами, я усовершенствовал виртуальный хост apache2 и получил успех.
Примечание: На сервере я успешно установил и работал над портом 9001 без каких-либо проблем. Эта направляющая линия для apache2 только без relavence с 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/ [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, чтобы включить сайт обязательна.