ash*_*540 41 javascript sockets node.js socket.io angularjs
我正在尝试将Socket.io与Angular集成,并且我很难从客户端到服务器建立连接.我查看了其他相关问题,但我的问题是在本地发生的,所以中间没有Web服务器.
这就是我的服务器代码:
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');
});
});
Run Code Online (Sandbox Code Playgroud)
我按以下顺序使用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,
...
]
}
Run Code Online (Sandbox Code Playgroud)
然后在我的控制器中:
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!' });
});
...
}
Run Code Online (Sandbox Code Playgroud)
在实际使用btford/angular-socket-io
库之前,我想确保我可以正确获得连接,但是在控制台中出现以下错误:
有趣的是,如果我重新启动Node.js服务器进程,它确实设法发送消息,但使用轮询而不是websockets.
我在socket.connect调用中尝试了各种不同的选项,但没有任何效果.
任何帮助,将不胜感激.
我刚刚意识到websockets部分工作.我在Chrome开发者控制台中看到了101切换协议请求.但是我看到的唯一框架是engine.io协议包(ping,pong).但是我的应用程序套接字消息仍然由于某种原因而退回到轮询...
ash*_*540 42
问题解决了!我只是弄清楚如何解决这个问题,但我仍然想知道这是否是正常行为.
似乎即使Websocket连接正确建立(由101交换协议请求指示),它仍然默认为长轮询.修复就像将此选项添加到Socket.io连接函数一样简单:
{transports: ['websocket']}
Run Code Online (Sandbox Code Playgroud)
所以代码最终看起来像这样:
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');
});
});
Run Code Online (Sandbox Code Playgroud)
在客户端:
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);
});
Run Code Online (Sandbox Code Playgroud)
消息现在显示为框架:
这个Github问题指出了我正确的方向.感谢所有帮帮忙的人!
Kat*_*rax 25
当前接受的解决方案具有误导性。
根据官方文档,添加该transports: [ 'websocket' ]
选项可以有效去除无法建立 websocket 连接时回退到长轮询的能力。这个选项首先使socket.io
如此强大,因为它可以适应许多场景。
在那种希望完全依赖 websockets 的特殊情况下,WebSocket API
建议直接使用。
对于其他情况(据说是大多数用户),这很可能是反向代理/服务器配置问题。
官方文档根据您的环境建议以下内容:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
另外值得一读这在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;
}
}
Run Code Online (Sandbox Code Playgroud)
Abh*_*eet 22
编辑您的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";
}
Run Code Online (Sandbox Code Playgroud)
小智 8
从您通过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-in-project
你可以:
传入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') }));
Run Code Online (Sandbox Code Playgroud)我也遇到过同样的问题,我改进了 apache2 虚拟主机输入并获得了成功。
注意:在服务器上我已成功安装并在 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>
Run Code Online (Sandbox Code Playgroud)
高级提示:请在 a2enmod 的帮助下启用 apache2 的所有 mod
重启apache2即可生效。但显然 a2ensite 需要启用站点。
注意:目前我的后端系统没有 https,所以我保留 http,如果您的后端已经启用了 HTTPS,则使用 https:// 作为后端。如果您的后端已经在 HTTPS 中,我担心 HTTPS 上的开销负载,我的建议是当私有服务器处于整洁的安全状态时,后端应该在 http 中。决定权在你。
小智 6
有同样的问题,我的应用程序在 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;
}
Run Code Online (Sandbox Code Playgroud)
小智 5
我通过将传输方式从“ websocket”更改为“轮询”解决了这一问题
var socket = io.connect('xxx.xxx.xxx.xxx:8000', {
transports: ['polling']
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
102955 次 |
最近记录: |