Javascript WebSocket连接失败:WebSocket握手期间出错:意外响应代码:400
我正在尝试将Socket.io与Angular集成,但在建立从客户端到服务器的连接时遇到了困难。我已经浏览过其他相关的问题,但是我的问题在本地发生,所以中间没有Web服务器。 这就是我的服务器代码的样子:Javascript WebSocket连接失败:WebSocket握手期间出错:意外响应代码:400,javascript,angularjs,node.js,sockets,socket.io,Javascript,Angularjs,Node.js,Sockets,Socket.io,我正在尝试将Socket.io与Angular集成,但在建立从客户端到服务器的连接时遇到了困难。我已经浏览过其他相关的问题,但是我的问题在本地发生,所以中间没有Web服务器。 这就是我的服务器代码的样子: const-app=express(); const server=http.createServer(app); const io=require('socket.io')。侦听(服务器); io.on('连接',函数(套接字){ emit('greet',{hello:'Hey,Mr.Cl
const-app=express();
const server=http.createServer(app);
const io=require('socket.io')。侦听(服务器);
io.on('连接',函数(套接字){
emit('greet',{hello:'Hey,Mr.Client!'});
socket.on('response',函数(数据){
控制台日志(数据);
});
socket.on('disconnect',function()){
log(“套接字断开”);
});
});
我正在使用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,
...
]
}
然后在我的控制器中:
函数MyController($scope){
让socket=io.connect(window.location.href);
socket.connect('http://localhost:3000');
socket.on('greet',函数(数据){
控制台日志(数据);
emit('respond',{消息:'Hello to you too,Mr.Server!'});
});
...
}
在实际使用btford/angular socket io
库之前,我想确保能够正确连接,但控制台中出现以下错误:
有趣的是,如果我重新启动Node.js服务器进程,它确实能够发送消息,但是使用轮询而不是WebSocket
我在socket.connect调用中尝试了各种不同的选项,但都没有成功
任何帮助都将不胜感激
更新(30/12/2016): 我刚刚意识到websockets在部分工作。我在Chrome开发者控制台中看到101交换协议请求。但是,我看到的唯一帧是engine.io协议包(ping、pong)。然而,由于某些原因,我的应用程序套接字消息仍然返回轮询
在控制器中,您使用的是
http
方案,但我认为您应该使用ws
方案,就像您使用WebSocket一样。尝试在连接函数中使用ws://localhost:3000
。我认为您应该为客户端定义源代码,如下所示:
//server.js
const socket=require('socket.io');
const-app=require('express')();
const server=app.listen('port');
const io=socket().attach(服务器);
io.origins(“您的\u域:端口www.your\u域:端口您的\u IP:port您的\u域:”)
io.on('连接',(套接字)=>{
log(“连接了一个新客户端”);
});
//client.js
var socket=io('ws://:port')代码>问题已解决!我只是想知道如何解决这个问题,但我仍然想知道这是否是正常行为
看起来,即使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);
});
消息现在显示为帧:
这为我指明了正确的方向。感谢所有帮助过我的人 从您通过Socket.IO发送的消息判断Socket.emit('greet',{hello:'Hey,Mr.Client!'})代码>,似乎您正在使用hackathonstarter
样板文件。如果是这样,问题可能是express status monitor
模块正在创建自己的socket.io实例,如下所示:
您可以:
移除该模块
创建expressStatusMonitor
实例时,将socket.io实例和端口作为websocket
传递,如下所示:
const server = require('http').Server(app);
const io = require('socket.io')(server);
...
app.use(expressStatusMonitor({ websocket: io, port: app.get('port') }));
这对我使用Nginx、节点服务器和Angular 4很有效
将nginx web服务器配置文件编辑为:
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";
}
我也遇到过同样的问题,我改进了apache2虚拟主机Entry并取得了成功
注意:在服务器上,我成功地安装并使用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>
ServerName pad.tejastank.com
ServerAlias pad.tejastank.com
服务器管理员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\u module/usr/lib/apache2/modules/mod\u headers.so
LoadModule deflate_module/usr/lib/apache2/modules/module_deflate.so
ProxyVia On
代理请求关闭
代理主机
ProxyPasshttp://localhost:9001/ 重试=0超时=30
ProxyPassReversehttp://localhost:9001/
#这是通过代理处理websocket传输所必需的,因为
#etherpad不使用特定的子文件夹,例如/ws/来处理此类流量。
#取自https://github.com/ether/etherpad-lite/issues/2318#issuecomment-63548542
#感谢博冈德森的语义学
重新启动发动机
RewriteCond%{QUERY_STRING}transport=websocket[NC]
重写规则/(*)ws://localhost:9001/socket.io/$1[P,L]
ProxyPasshttp://localhost:9001/socket.io 重试=0超时=30
ProxyPassReversehttp://localhost:9001/socket.io
选项如下符号链接多视图
允许超越所有
命令允许,拒绝
通融
提前提示:
请在a2enmod的帮助下启用apache2的所有mod
重新启动apache2将生效。但显然需要一个启用站点的敏感度。您正在客户端使用端口3000。我猜是角端口而不是服务器端口?它应该连接到服务器端口。使用以下负载平衡器设置后,我的问题已为wss解决,但对于ws,特定ISP的问题仍然存在
I s
var socket = io.connect('xxx.xxx.xxx.xxx:8000', {
transports: ['polling']
});
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;
}
}
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
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
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;
}
}
<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>
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;
}
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')
}));
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}`)
})
const app = require("express")();
const http = require("http").Server(app);
const io = require("socket.io")(http);
http.listen(PORT,()=> console.log('listening'))
app.listen(......)