Не удалось подключиться к 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');
});
});
Я загружаю файлы 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
, я хочу убедиться, что я могу правильно установить соединение, но я получаю следующую ошибку в консоли:
![сообщение об ошибке соединения сокета io]()
Интересно, что если я перезапущу серверный процесс Node.js, ему удастся отправить сообщение, но с помощью опроса вместо веб-сайтов.
![после перезапуска]()
![сообщение для опроса]()
Я пробовал всевозможные опции в вызове socket.connect, но ничего не работало.
Любая помощь будет оценена.
ОБНОВЛЕНИЕ (30/12/2016):
Я только понял, что websockets работает частично. Я вижу запрос 101 Switching Protocols в консоли разработчика Chrome. Однако единственными кадрами, которые я вижу там, являются пакеты протокола engine.io(пинг, понг). Однако мои сообщения сокета приложения все еще возвращаются к опросу по какой-то причине...
![engine.io-пакеты]()
Ответы
Ответ 1
Проблема решена! Я просто понял, как решить проблему, но мне все равно хотелось бы знать, нормальное поведение или нет.
Похоже, что даже если соединение Websocket правильно установлено (указано в запросе 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 указал мне в правильном направлении. Спасибо всем, кто помог!
Ответ 2
Это работало для меня с сервером 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";
}
Ответ 3
Судя по сообщениям, которые вы отправляете через Socket.IO 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- в-проект
Вы также можете:
- Удалить этот модуль
-
Передайте ваш экземпляр socket.io и порт как websocket
при создании экземпляра expressStatusMonitor
как expressStatusMonitor
ниже:
const server = require('http').Server(app);
const io = require('socket.io')(server);
...
app.use(expressStatusMonitor({ websocket: io, port: app.get('port') }));
Ответ 4
Я решил это, изменив транспорты с "websocket" на "опрос"
var socket = io.connect('xxx.xxx.xxx.xxx:8000', {
transports: ['polling']
});
Ответ 5
Я столкнулся с такими же проблемами, я усовершенствовал процесс виртуального хоста apache2 и получил успех.
Примечание. На сервере я успешно установил и работал на сервере 9001 без каких-либо проблем. Эта направляющая строка для apache2 не имеет отношения к nginx, этот ответ для любителей 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>
Советы по продвижению:
Пожалуйста, с помощью a2enmod включить весь mod of apache2
Перезапустите apache2, чем получите эффект. Но очевидный a2ensite для обеспечения требуемого сайта.
Ответ 6
В вашем контроллере вы используете схему http
, но я думаю, что вы должны использовать схему ws
, поскольку вы используете websockets. Попытайтесь использовать ws://localhost:3000
в своей функции подключения.
Ответ 7
Я думаю, что вы должны определить свою 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');
Ответ 8
Вы используете порт 3000 на стороне клиента. Я бы рискнул предположить, что угловой порт, а не порт сервера? Это должно быть подключение к порту сервера.
Ответ 9
После использования следующей настройки балансировки нагрузки моя проблема решена для wss, но для ws проблема все еще существует для конкретного провайдера.
calssic-балансировки нагрузки
Ответ 10
Я решил это, удалив io.listen(server);
. Я начал сталкиваться с этой ошибкой, когда начал интегрировать passport.socketio и использовать промежуточное ПО для паспортов.