事件页面卸载后无法在Chrome上接收UDP套接字的回调 [英] Not getting onReceive callback for UDP socket on chrome after event page is unloaded

查看:150
本文介绍了事件页面卸载后无法在Chrome上接收UDP套接字的回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个chrome应用程序(打包),我必须创建一个UDP套接字,并在chrome浏览器启动后立即侦听传入的广播消息.

I am creating a chrome app (packaged) and I have to create a UDP socket and listen for the incoming broadcast messages as soon as chrome browser starts up.

启动浏览器时一切正常,我通过chrome.sockets.udp.onReceive.addListener() API和数据注册了回调.

Everything works fine as I start browser , I get the callback registered through chrome.sockets.udp.onReceive.addListener() API and the data as well.

卸载事件页面时(大约10-15秒后),问题开始.

The problem starts when the event page is unloaded (after about 10-15 secs).

未接收到任何新的UDP数据包.

Any new UDP packets are not received.

但是,如Chrome Apps & Extensions Developer Tool所示,即使事件页面被卸载后,onReceive回调也会触发一次(但不适用于后续的UDP数据包),但是它没有达到我的回调函数.

But as seen in Chrome Apps & Extensions Developer Tool , onReceive callback triggered once even after the event page is unloaded (but not for subsequent UDP packets),but it doesn't hit my callback function.

在创建UDP套接字时,我一直将persistent标志保留为true.

And I have kept the persistent flag true while creating the UDP socket.

这是我的应用程序的清单:

Here is the manifest of my app:

{
  "manifest_version": 2,

  "name": "App Name",
  "description": "Description",
  "version": "1.0",

  "app": {
    "background": {
      "scripts": ["socket.js","eventPage.js"],
    "persistent": true
    }
  },
  "sockets":{
    "udp": {"send":["*:*"], "bind":["*:*"]}
  }, 
  "permissions":["system.network","notifications"]
}

事件页面和套接字代码:

Event page and socket code:

// eventPage.js

chrome.runtime.onStartup.addListener(function() { 
    console.log("I started up!");
    socket.cleanup_create();
});

chrome.runtime.onSuspend.addListener(function() {
    console.log("I am being suspended!");
});

// socket.js

function show(jsontext) {

    var json_object = JSON.parse(jsontext);

    console.log(json_object.TitleText); 
    console.log(json_object.MainText);

    chrome.notifications.create("", 
            {type:'basic',iconUrl:'icon.png',title:json_object.TitleText,message:json_object.MainText}, 
            function callback(){})
}

var socket = {

    socketId:null,

    /*==========Receive Callback=================*/
    recieve_callback:function(rc){
    console.log("Received on socket ID "+rc.socketId);

    var dataView = new DataView(rc.data);


    var decoder = new TextDecoder("utf-8");
    var decodedString = decoder.decode(dataView);


    console.log("Data Received and it is "+decodedString);

    show(decodedString);

    },

    /*==========Receive Error Callback=================*/

    recieve_error_callback:function(info){
    console.log("Error on socket with code "+info.resultCode);
    },

    /*==========Bind Callback=================*/

    bind_cb: function(s){
    console.log("Socket seems to be binded result "+s);
    chrome.sockets.udp.onReceive.addListener(socket.recieve_callback)
    chrome.sockets.udp.onReceiveError.addListener(socket.recieve_error_callback)
    },

    /*==========Create Callback=================*/

    create_cb: function(s){
    console.log("Socket seems to be created id is "+s.socketId);
    socket.socketId = s.socketId;
    chrome.sockets.udp.bind(socket.socketId,"0.0.0.0",8080,socket.bind_cb);
    },

    /*==========Create Method=================*/

    create: function(){
    chrome.sockets.udp.create({persistent:true,name:"udp_socket",bufferSize:15000},socket.create_cb);   
    },

    cleanup_create:function(){
    chrome.sockets.udp.getSockets(function cleanup_create_cb(socketInfos){
    console.log("Cleaning up existing sockets  "+socketInfos.length);

    for (i = 0; i < socketInfos.length; i++) {
    chrome.sockets.udp.close(socketInfos[i],function socket_close_cb(){});
    }

    socket.create();

    });
    }
};

有什么方法可以使事件页面始终保持加载状态,或者可以通过其他任何方式确保始终获得onReceive事件?

Is there any way I can keep the event page always loaded or any other means through which I can ensure that I always get the onReceive event?

推荐答案

Chrome事件页面如何工作?这是文档,但总而言之:

How do Chrome event pages work? Here's the documentation, but in a nutshell:

  1. 您页面的顶级上下文将执行,注册事件的侦听器.
  2. Chrome会建立一系列事件,以唤醒该页面.
  3. 页面卸载:请注意,它会完全破坏JS上下文,包括侦听器和所有初始化的对象(例如,您的socket对象).
  4. 事件发生. Chrome会在需要唤醒您的页面时进行查找.假设确实如此.
  5. 再次加载页面,侦听器再次注册 ,然后Chrome对其进行调用.
  1. Your page's top level context executes, registering listeners for events.
  2. Chrome builds a list of events that it should wake the page for.
  3. Page unloads: note that it completely destroys JS context, including listeners and any objects initialized (e.g. your socket object).
  4. Event happens. Chrome looks up if it needs to wake up your page. Suppose it does.
  5. The page is loaded again, listeners register again, and then Chrome calls them.

引用文档:

因为侦听器本身仅存在于事件页面的上下文中,所以每次加载事件页面时都必须使用addListener;仅靠runtime.onInstalled这样做是不够的.

Because the listeners themselves only exist in the context of the event page, you must use addListener each time the event page loads; only doing so at runtime.onInstalled by itself is insufficient.

现在让我们看一下这一行:

Now let's look at this line:

// Called in a callback to chrome.sockets.udp.bind()
bind_cb: function(s){
  /* ... */
  chrome.sockets.udp.onReceive.addListener(socket.recieve_callback)
  /* ... */
}

再次加载页面时,它不会同步执行.因此,在第5步中,Chrome无法找到合适的监听器,因此未调用它.

When the page is loaded again, this does not execute synchronously. Therefore, at step 5, Chrome fails to find an appropriate listener and it's not called.

请注意,该事件是全局事件,即未绑定到套接字对象(卸载后不存在).因此,您可以(并且应该)安全地将其绑定到一个用于分析回调参数以了解其在哪个套接字上运行的函数.

Do note that the event is global, i.e. it's not bound to a socket object (that does not exist after unloading). So you can (and should) safely bind it to one function that analyzes the callback parameters to understand which socket it operates on.

因此,要使您的代码正常工作,必须在事件页面加载时同步调用addListener .

So, to make your code work, addListener must be called synchronously when the event page loads.

这篇关于事件页面卸载后无法在Chrome上接收UDP套接字的回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆