根据我的搜索,这应该不是那么难,到目前为止我已经尝试了许多没有运气的事情。我有一个在Heroku上运行的Node.js服务器,它创建了一个socket.io服务器(我也试过在Nodejitsu上托管它,但没有帮助)。如果我从我想创建websocket连接的实际Node.js服务器提供页面,socket.io套接字连接没有问题,但是我无法使我的任何跨域套接字连接尝试工作。< / p>
我尝试过几种方式跨域连接到这个socket.io服务器:
(1)一个简单的本地HTML文件,其中包含一些脚本,可以从节点服务器(使用$ .getScript)成功获取客户端socket.io库,然后尝试创建套接字连接(var socket = io.connect(' nodejs_server_hostname:port_num');),失败。
(2)在本地运行rails app服务器(开发模式),它为包含javascript的客户端提供响应,尝试以与方法(1)相同的方式形成websocket连接,并且失败
(3)在Heroku中托管rails应用程序,并执行与方法(2)相同的操作。这也失败了。我确保启用Heroku文档(https://devcenter.heroku.com/articles/heroku-labs-websockets)中指定的websockets。再一次,如果请求是从实际的Node.js服务器提供的,客户端尝试与。形成socket.io连接,则一切正常。
在所有三次尝试中都会触发socket.socket.on('error')事件。
我尝试使用以下代码修改rails应用中的http响应标头:
response.headers['Access-Control-Allow-Origin'] = '*'
这会正确设置标头(我在从rails服务器请求页面后检查过),但它不能解决套接字连接问题。
我在Node.js服务器上创建了一个执行日志记录的socket-io授权回调,看起来这个回调根本就没有用于跨域套接字连接尝试。所以似乎Node.js服务器甚至从未看到websocket连接尝试,这对我来说非常困惑。
下面我将粘贴所有相关的代码文件。
Node.js服务器文件:
var http = require('http'),
express = require('express'),
whiskers = require('whiskers'),
redis = require('redis'),
port = process.env.PORT || 5000,
app = express(),
server = http.createServer(app).listen(port),
io = require('socket.io').listen(server);
console.log('---- ' + port);
console.log(port);
console.log('---- ' + port);
io.configure(function () {
io.set('authorization', function (handshakeData, callback) {
console.log("-- inside io.set('authorization, cb)")
console.log('-- handshakeData:');
console.log(handshakeData);
console.log('-- end of handshakeData logging --');
callback(null, true); // error first callback style
});
});
app.configure(function() {
app.use(express.static(__dirname + '/public'));
app.set('views', __dirname + '/views');
app.set('view options', { layout: false });
app.engine('.html', whiskers.__express);
});
app.get('/', function(req, res) {
res.render('index.html');
});
io.sockets.on('connection', function(socket) {
console.log('---- new client connected ----');
console.log(socket);
console.log('---- end of socket details logging for new client connection ----');
socket.emit('news', { hello: 'world' });
socket.on('my other event', function(data) {
console.log("-- server -- inside socket.on 'my other event' callback");
console.log(data);
});
socket.on('button clicked', function(data) {
console.log("-- server -- inside socket.on 'button clicked' callback");
console.log(data);
io.sockets.emit('news', { info: 'the button was clicked' });
});
});
以下是Rails app的客户端javascript文件:
$(document).ready(function() {
console.log('-- inside chat.js -- document is ready');
$('#join-chat-container').hide();
$('#new-message-container').hide();
//$.getScript('http://node-server-for-rails-chat.herokuapp.com/socket.io/socket.io.js')
$.getScript('http://node-server-for-rails-chat.jit.su/socket.io/socket.io.js')
.done(function( script, textStatus ) {
console.log("-- socket.io.js loaded and executed -- textStatus: " + textStatus);
setup_socket();
})
.fail(function( jqxhr, settings, exception ) {
console.log("-- socket.io.js load error -- exception:");
console.log(exception);
console.log("-- jqxhr: " + jqxhr);
});
});
function setup_socket() {
//var socket = io.connect('node-server-for-rails-chat.herokuapp.com', { port: 19364 });
//var socket = io.connect('node-server-for-rails-chat.jit.su', { port: 5000 });
var socket = io.connect('node-server-for-rails-chat.herokuapp.com:27305');
socket.socket.on('error', function (reason) {
console.log('--- cant connect');
console.log(reason);
console.error('Unable to connect Socket.IO', reason);
});
socket.on('connect_failed', function() {
console.log('connect failed');
});
socket.on('connect', function() {
console.log('successfully connected!');
});
socket.on('message', function (message_html) {
console.log("-- client -- inside socket.on('message', cb) callback");
console.log("-- client -- message_html: " + message_html);
add_message(message_html);
});
if (!socket.socket.connected) {
console.log(socket);
console.log("-- Error connecting with socket");
}
socket_loaded(socket);
};
function socket_loaded(socket) {
// this part contains irrelevant (not socket related) code
}
//more irrelevant code excluded for brevity (add_message function, plus other stuff)
这是我在浏览器中本地打开的独立HTML文件:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-git.js"></script>
<script>
$(document).ready(function() {
if (typeof jQuery !== 'undefined') {
console.log('-- client -- jQuery library loaded successfully');
$('#myButton').on('click', function() {
console.log("-- client -- inside jquery '#myButton' click callback");
socket.emit('button clicked', { button: '#myButton' });
});
}
$.getScript('http://node-server-for-rails-chat.herokuapp.com/socket.io/socket.io.js')
.done(function( script, textStatus ) {
console.log("-- socket.io.js loaded and executed -- textStatus: " + textStatus);
socket_is_loaded();
})
.fail(function( jqxhr, settings, exception ) {
console.log("-- socket.io.js load error -- exception:");
console.log(exception);
console.log("-- jqxhr: " + jqxhr);
});
});
function socket_is_loaded() {
//var socket = io.connect('node-server-for-rails-chat.jit.su:5000');
var socket = io.connect('node-server-for-rails-chat.herokuapp.com:27305');
socket.socket.on('error', function (reason) {
console.log('--- cant connect');
console.log(reason);
console.error('Unable to connect Socket.IO', reason);
});
socket.on('connect_failed', function() {
console.log('connect failed');
});
socket.on('connect', function() {
console.log('successfully connected!');
});
socket.on('news', function(data) {
console.log("-- client -- inside socket.on 'news' callback");
console.log(data);
//socket.emit('my other event', { my: 'data' });
});
}
</script>
</head>
<body>
<h1>Socket.io How-to-use Example Script</h1>
<input type='button' id='myButton' value='click me!'/>
</body>
</html>
有没有人对我如何解决这个问题有所了解?非常感谢。
答案 0 :(得分:3)
我有类似的设置正在运行,并且必须在节点快速Web服务器上配置以下标头。
app = require('express')();
...
app.use(function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type');
return next();
});
答案 1 :(得分:0)
Socket.IO版本 - &gt; 1.3.7 强> 快递版 - &gt; 4.13.3 强>
选项1:仅强制使用网页
默认情况下,websockets是跨域的。如果强制Socket.io仅将其用作连接客户端和服务器的方法,那么你就可以了。
服务器端
//HTTP Server
var server = require('http').createServer(app).listen(8888);
var io = require('socket.io').listen(server);
//Allow Cross Domain Requests
io.set('transports', [ 'websocket' ]);
客户端
var connectionOptions = {
"force new connection" : true,
"reconnectionAttempts": "Infinity", //avoid having user reconnect manually in order to prevent dead clients after a server restart
"timeout" : 10000, //before connect_error and connect_timeout are emitted.
"transports" : ["websocket"]
};
var socket = io("ur-node-server-domain", connectionOptions);
就是这样。问题?不适用于不支持websockets的浏览器(适用于客户端)。有了这个,你几乎杀死了Socket.io的魔力,因为它逐渐开始长时间轮询,以后升级到websockets(如果客户端支持它。)
如果您100%确定所有客户都可以使用符合HTML5标准的浏览器访问,那么您就可以了。
选项2:允许服务器端的CORS,让Socket.io处理是否使用websockets或长轮询。
对于这种情况,您只需要调整服务器端设置。客户端连接与以前一样。
服务器端
//HTTP Server
var express=require('express');
//Express instance
var app = express();
//ENABLE CORS
app.all('/', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
就是这样。希望它可以帮助其他人。请记住,对于第二个选项,非常重要的是// ENABLE CORS部分是您应用于快速实例的第一件事(express());