【问题标题】:Node.js with ZeroMQ + Socket.io + scoping per clientNode.js 与 ZeroMQ + Socket.io + 每个客户端的范围
【发布时间】:2014-01-21 03:44:50
【问题描述】:

我正在使用 node.js 和 express 编写一个 Web 应用程序,以通过 ZeroMQ 和 socket.io 向每个用户提供实时 aprs 流。

概念是:node.js 应用通过订阅 ZeroMQ 发布者将完整的 aprs 流发送给它。当用户访问网页(全屏地图)时,socket.io 会话被建立并将地图当前可见区域的边界发送回服务器。然后,服务器可以将完整提要的范围限定为仅将地图上的新地点发送给用户。

其中大部分都运行良好,但当超过一个人加载网站时它会中断。当前查看的地图的范围变为全局,如果您缩放/平移一张地图,它将开始向两个浏览器显示新位置上的点。

我需要每个 socket.io 会话保留自己的范围,并且只从其唯一范围的地图边界接收数据,并且对每个访问者都是唯一的。我尝试在 socket.io 连接中嵌套zmqsocket.on "message", (data) -> 回调,但它仍然产生相同的结果(即使在正确的回调中声明了 mapbounds 变量。)

应用程序的完整来源可以在这里找到:https://github.com/gmcintire/aprs.bz

如果你想在本地测试应用程序,你应该可以克隆我的 repo,运行npm install,然后运行coffee app.coffee 开始。请注意,它将开始从我的 ZeroMQ 服务器流式传输完整的 APRS 提要,这可能是 ~100KBytes/sec。

app.coffee

express = require("express")
routes = require("./routes")
geolib = require("geolib")
zmq = require("zmq")
zmqsocket = zmq.socket("sub")

zmqsocket.connect "tcp://stream.aprs.bz:12777"
zmqsocket.subscribe ""
app = module.exports = express.createServer()
io = require("socket.io").listen(app)

mapbounds = ""

io.sockets.on "connection", (socket) ->
  #console.log socket
  socket.on "mapmove", (mapcoords) ->
    console.log mapbounds
    mapbounds = mapcoords

zmqsocket.on "message", (data) ->
  packet = JSON.parse(data)
  #console.log packet

  if packet.latitude? and packet.longitude? and (mapbounds != "")
    insideMap = geolib.isPointInside
      latitude: packet.latitude
      longitude: packet.longitude
    , [
      latitude: mapbounds._northEast.lat
      longitude: mapbounds._southWest.lng
    ,
      latitude: mapbounds._northEast.lat
      longitude: mapbounds._northEast.lng
    ,
      latitude: mapbounds._southWest.lat
      longitude: mapbounds._northEast.lng
    ,
      latitude: mapbounds._southWest.lat
      longitude: mapbounds._southWest.lng
    ]
    if insideMap
      console.log "\n--------------------------------------------------------\n"
      io.sockets.emit "packet", packet
      console.log packet

app.configure ->
  app.set "views", __dirname + "/views"
  app.set "view engine", "jade"
  app.use express.bodyParser()
  app.use express.methodOverride()
  app.use app.router
  app.use express.static(__dirname + "/public")

app.configure "development", ->
  app.use express.errorHandler(
    dumpExceptions: true
    showStack: true
  )

app.configure "production", ->
  app.use express.errorHandler()

app.get "/", routes.index
if app.settings.env == "development"
  app.listen 3000
else
  app.listen 80

console.log "Express server listening on port %d in %s mode", app.address().port, app.settings.env

【问题讨论】:

    标签: node.js socket.io zeromq


    【解决方案1】:

    我也不是 CS 或 ZMQ 人,但听起来您正在向太多客户广播数据。 io.sockets.emit 将向所有连接的套接字发送事件。如果您只想将数据发送到 1 个套接字,则应使用 socket.emit,其中 socket 已设置为单个套接字对象。

    【讨论】:

    • 感谢您帮助我错过了这一疏忽。我以为因为我没有使用 sockets.broadcast 它不会发送给所有客户,但你是对的。将整个 zmqsocket.on "message", (data) -> 事件侦听器更改为嵌套在 io.sockets.on "connection", (socket) -> 中并将其更改为 socket.emit 效果非常好。谢谢!
    【解决方案2】:

    我没有使用 Coffee 的经验,但我可以看到您正在全局存储变量。

    var mapboudns = 10
    io.sockets.on('connection', function(socket){
        socket.on("msg", function(data){
          mapbounds = data.bounds; //new value of mapbounds is altered globally
        });
    });
    

    尝试使用类似的东西:

    socket.set("mapbounds", someNewValue);
    

    稍后获取值:

    socket.get("mapbounds");
    

    或使用集合将每个套接字映射到其相关变量

    【讨论】:

    • 只是旁注,但我相信您需要将回调传递给 get(key, fn) 以检索值:github.com/LearnBoost/socket.io/blob/master/lib/stores/…
    • 感谢您的帮助。我曾尝试将每个套接字的范围映射到数组中的相关变量,但一直得到相同的结果,它只在全局范围内被引用。
    猜你喜欢
    • 1970-01-01
    • 2016-05-31
    • 2014-04-22
    • 1970-01-01
    • 2013-03-04
    • 2020-10-14
    • 2011-11-12
    • 2020-04-07
    • 2019-04-15
    相关资源
    最近更新 更多