在创建窗口之前,Chrome应用程序不会在background.js中接收外部UDP数据

时间:2017-10-24 06:03:10

标签: javascript network-programming udp google-chrome-app google-chrome-os

我尝试为Chromebook创建的应用(Chrome OS 60.0.3112.114 64位)侦听UDP广播,当此类消息到达时,我希望它打开一个窗口。到目前为止,当JS被添加到窗口时,一切都很好,但是应用程序的目的是安静地收听消息,只有在收到消息后才会打开窗口。

所有代码都已移至background.js,现在它从未收到ouside消息。首先想到的是它被暂停,所以我在background.js中添加了一个setInterval来向我自己发送数据,模拟外部数据到达并正确接收这些消息,脚本没有休眠。当我创建任何类型的窗口时,魔法开始,我立即开始接收广播。当我关闭窗口时外部数据被中断,我仍然可以从setInterval发送所有自己的消息。

这有什么解决方案吗?我试图做的下一件事是创建一个隐藏的窗口,但没有这样的东西,也尝试使用background.html并在background.js代码中放置iframe将导致相同的行为。

的manifest.json

{
  "name": "UDP Sample",
  "description": "Can't receive data",
  "version": "0.1",
  "manifest_version": 2,

  "app": {
    "background": {
      "scripts": ["background.js"],
      "persistent": false
    }
  },

  "icons": {
    "16": "calculator-16.png",
    "128": "calculator-128.png"
  },

  "sockets": {
      "udp": {
        "send": "*",
        "bind": "0.0.0.0:13000"
      }
  },
}

background.js:

chrome.app.runtime.onLaunched.addListener(StartApp);

var socketId;

function StartApp()
{
  console.log('app started');

  chrome.sockets.udp.onReceive.addListener(SockRecv);
  chrome.sockets.udp.onReceiveError.addListener(SockError);

  SockBind(AppReady, AppError);
}

function AppReady()
{
  setInterval(function()
  {
    console.log("self sending data");

    var buf = new Uint8Array([70, 73, 82, 69]);
    SockSend(false, buf.buffer);
  }, 4000);

  console.log('listening for net events.');
}

function AppError()
{
  console.log('bind failed, retrying in 10 seconds.');
  setTimeout(StartApp, 10000);
}

function LaunchWindow()
{
  chrome.app.window.create('about.html', 
  {
    frame: "none",
    resizable: false,
    outerBounds: {
      'width': 400,
      'height': 300
    }
  });
}

function SockRecv(info)
{
  console.log("data received " + info.remoteAddress + " bytes");

  if (info.socketId !== socketId || info.remoteAddress == '127.0.0.1')
    return;

  LaunchWindow();
}

function SockSend(ip,data)
{
  chrome.sockets.udp.send(socketId, data, '127.0.0.1', 13000, function()
  {
    console.log("data sent");
  });
}

function SockError(info)
{
  console.log("something bad happened");
  if (info.socketId !== socketId)
    return;

  chrome.sockets.udp.setPaused(socketId, false, function(){});
}

function SockBind(ready_func, error_func)
{
  // Create the Socket
  chrome.sockets.udp.create({persistent: true},
  function(socketInfo)
  {
    console.log("new socket created");
    socketId = socketInfo.socketId;
    try
    {
      chrome.sockets.udp.bind(socketId, "0.0.0.0", 13000, function(result)
      {
        if (result < 0)
        {
          result = socketId;
          socketId = false;
          chrome.sockets.udp.close(result, error_func);
        }
        else
          ready_func();
      });
    }
    catch(err)
    {
      error_func();
    }
  });
}

控制台调试(我手动执行函数LaunchWindow,突然外部数据到达):

background.js:7 app started
background.js:80 new socket created
background.js:25 listening for net events.
background.js:19 self sending data
background.js:61 data sent
background.js:49 data received 127.0.0.1 bytes
background.js:19 self sending data
background.js:61 data sent
background.js:49 data received 127.0.0.1 bytes
background.js:19 self sending data
background.js:61 data sent
background.js:49 data received 127.0.0.1 bytes
LaunchWindow()
undefined
background.js:49 data received 192.168.1.49 bytes
background.js:19 self sending data
background.js:61 data sent
background.js:49 data received 127.0.0.1 bytes
background.js:49 data received 192.168.1.49 bytes
background.js:19 self sending data
background.js:61 data sent
background.js:49 data received 127.0.0.1 bytes
background.js:49 data received 192.168.1.49 bytes
background.js:19 self sending data

netstat -l的输出证明套接字正在等待数据:

chronos@localhost / $ netstat -l
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN     
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN     
udp        0      0 0.0.0.0:13000           0.0.0.0:*                          
udp        0      0 0.0.0.0:bootpc          0.0.0.0:*                          
udp        0      0 0.0.0.0:mdns            0.0.0.0:*                          
udp        0      0 0.0.0.0:mdns            0.0.0.0:*                          
udp6       0      0 [::]:mdns               [::]:*                             

1 个答案:

答案 0 :(得分:0)

ChromeOS有一个防火墙,可以防止侦听套接字在没有活动的应用程序窗口时接受新连接。

我发现,最好的解决方案是创建一个 prepareAd(); ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); scheduler.scheduleAtFixedRate(new Runnable() { public void run() { Log.i("Hello", "World"); runOnUiThread(new Runnable() { public void run() { if (mInterstitialAd.isLoaded()) { mInterstitialAd.show(); } else { Log.d("TAG", "The interstitial wasn't loaded yet."); } prepareAd(); } }); } }, 55, 285,TimeUnit.SECONDS); } public void prepareAd() { mInterstitialAd = new InterstitialAd(this); mInterstitialAd.setAdUnitId("ca-app-pub-3940256099942544/1033173712"); mInterstitialAd.loadAd(new AdRequest.Builder().build()); } 类型的窗口,它不是隐藏的,而是最小化的。您可以使用https://github.com/kzahel/connection-forwarder查看示例实现,或在网上商店中查看演示:https://chrome.google.com/webstore/detail/connection-forwarder/ahaijnonphgkgnkbklchdhclailflinn