【问题标题】:Cross-domain connection in Socket.IOSocket.IO 中的跨域连接
【发布时间】:2012-02-16 18:11:36
【问题描述】:

可以跨域使用Socket.IO吗?如果是这样,怎么做?网上都提到了这种可能性,但没有在任何地方给出代码示例。

【问题讨论】:

    标签: javascript websocket socket.io cors cross-domain


    【解决方案1】:

    引用socket.io FAQ

    Socket.IO 是否支持跨域连接?

    当然,在每个浏览器上!

    至于它是如何做到的:Native WebSockets 在设计上是跨域的,socket.io 提供了一个用于跨域 flash 通信的 flash 策略文件,XHR2 可以使用 CORS,最后你可以始终使用 JSONP。

    【讨论】:

    • 我实际上遇到了跨域 socket.io 连接的一些问题。当 socket.io 恢复到 XHR-Polling/Ajax 时,socket.io 会尝试向当前域 /socket.io/1 发出请求,这会导致无法 'onClose ' 在 null 上。谷歌搜索这个错误会引发几个 github 问题,但没有什么适用于我的情况(因为我认为这是配置问题,而不是错误)。
    • 这个答案已经过时了。浏览器在 webSockets 上实现同源保护,就像它们对 Ajax 调用所做的一样。如果您希望允许跨源 socket.io 连接,则必须在您的 socket.io 服务器中显式启用。
    【解决方案2】:

    **Socket.IO 版本 --> 1.3.7 **

    可以跨域使用Socket.Io吗? 是的,绝对的。

    如果有,怎么做?

    选项 1:仅强制使用 Websockets

    默认情况下,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();
     });
    

    就是这样。希望它可以帮助其他人。

    【讨论】:

      【解决方案3】:

      在创建客户端套接字时只需插入您的远程域名:

      var socket = io.connect('http://example.com:8080');
      

      【讨论】:

      • 答案太旧了。 io.connect 不是一个函数。
      • io.connect 应该仍在工作(2016 年):socket.io/docs/#using-with-express-3/4。另请参阅 socket.io/docs/client-api/: "connect Fired on a successful connection."
      【解决方案4】:

      Socket.io 支持跨域连接,但请记住,您的 cookie 不会传递给服务器。您必须:

      (1) 提出一个替代标识方案(自定义令牌或 javascript cookie - 请记住,这不应该是实际的会话 ID,除非您想让自己面临会话劫持的风险)

      或 (2) 首先向服务器发送一个良好的老式 HTTP JSONP 请求以获取 cookie。然后它将通过套接字连接握手进行传输。

      【讨论】:

      • 卡在确切的问题上,我无法将 cookie 传递给服务器。在角度实现这一目标的最佳实践是什么
      【解决方案5】:

      像这样通过 io 创建你的服务器:

      const server = require('http').createServer();
      
      const io = require('socket.io')(server, {
          origins:["127.0.0.1:8000"],
          path: '/',
          serveClient: false,
          // below are engine.IO options
          pingInterval: 20000,
          pingTimeout: 5000,
          cookie: false
      });
      
      io.on('connection', function(socket){
          console.log("here new user welcom")
      });
      
      
      server.listen(3000,function(){
          console.log('listening on *:3000')});
      

      在原点数组中指定有效原点

      【讨论】:

      【解决方案6】:

      简单又安全!

      在主文件中将其放在 io.on('connection') 之前,添加以下行:

      io.set('origins', 'yoursite.com:*');
      
      io.on('connection', function (socket) {
      

      【讨论】:

        【解决方案7】:

        是的。 我已经实现了跨域socket.io来测试它是否有效。

        <script src="http://your-nodejs-domain.com:3000/public/js/jquery.js"></script>
          <script src="http://your-nodejs-domain.com:3000/socket.io/socket.io.js"></script>
          <script>
        
              var socket = io.connect('http://your-nodejs-domain:3000');
              $(document).ready(function(){
        
                  socket.on('test message', function(msg){
                       console.log("Got the message: " + msg);
                  });
              });
        
          </script>
        

        应该没问题。

        【讨论】:

        • 能否给出server.js app的完整代码
        【解决方案8】:

        从 v4 开始,根据the docs

        从 Socket.IO v3 开始,您需要显式启用Cross-Origin Resource Sharing (CORS)。

        您可以在传递给new Server() 的配置对象中使用cors 键。看到这个basic example from the above docs page

        import { createServer } from "http";
        import { Server } from "socket.io";
        
        const httpServer = createServer();
        const io = new Server(httpServer, {
          cors: {
            origin: "https://example.com"
          }
        });
        

        origin 可以是一个接受多个来源的数组。

        其他选项包括 allowRequestallowedHeaderswithCredentialsextraHeaders and others from the cors package,它们最终在后台处理 CORS 标头。

        我还测试了与 this answer 稍有不同的语法,后者在 4.4.1 中对我有用:

        const express = require("express");
        const app = express();
        const server = require("http").createServer(app);
        const io = require("socket.io")(server, {
          cors: {origin: ["https://glitch.me", "https://cdpn.io"]}
        });
        

        【讨论】:

          猜你喜欢
          • 2012-07-16
          • 2013-10-03
          • 2015-04-04
          • 2014-10-03
          • 2013-01-06
          • 2015-04-10
          • 1970-01-01
          • 2012-08-06
          • 2013-12-04
          相关资源
          最近更新 更多