本地应用和 Chrome 扩展之间的通信

8
我有一个用c++编写的本地应用程序和一个Chrome扩展程序。
我使用“Chrome原生消息传递”在它们之间通信。
本地应用程序代码:
int main(int argc, char* argv[]) {
 unsigned int a, c, i, t=0;
 std::string inp;  do {
 inp="";
 t=0;
 // Sum the first 4 chars from stdin (the length of the message passed).
  for (i = 0; i <= 3; i++) {
    t += getchar();
  }

  // Loop getchar to pull in the message until we reach the total
  //  length provided.
  for (i=0; i < t; i++) {
    c = getchar();
    inp += c;
  }

// Collect the length of the message
unsigned int len = inp.length();
//// We need to send the 4 btyes of length information
std::cout << char(((len>>0) & 0xFF))
          << char(((len>>8) & 0xFF))
          << char(((len>>16) & 0xFF))
          << char(((len>>24) & 0xFF));
//// Now we can output our message
std::cout << inp <<std::endl;
flushall();
}while(cnt < 2 );
return 0;  }

我正在读取由Chrome扩展程序在标准输入上发送的消息,并通过将其写入标准输出来发送相同的消息。扩展程序使用PostMessage()。这个方法可以工作,但是当我将我的程序放在一个连续的while循环下时,流程只会被执行一次!也就是说,port.postMessage({'text':'hello_1'})会得到预期的回显,但如果我执行port.postMessage({'text':'hello_2'}), 它不会被回显。我无法理解问题所在。它需要线程吗?请帮忙!谢谢!
3个回答

10

Marc的回答包含一些错误(源自问题),对于长度不符合一个字节的消息将无法工作。

Chrome与本地应用程序通信时的协议如下:

  • 通过stdin接收到本地应用程序的请求
  • 通过stdout发送响应给Chrome
  • Chrome处理Windows风格的\r\n不好,因此在消息中避免使用该字符,并将stdin模式设置为二进制(以便可以正确读取请求长度,\n不会转换为\r\n):

_setmode(_fileno(stdin),_O_BINARY);

请求和响应消息是 JSON 格式的,具有包含消息长度的 4 字节头部(uint32):

[length 4 byte header][message]

读取请求头部:

uint32_t reqLen = 0;
cin.read(reinterpret_cast<char*>(&reqLen) ,4);

编写响应头:

cout.write(reinterpret_cast<char*>(&responseLen),4); 

亲爱的@bkdc,我有一个问题,本地消息传递的类型是什么?它是Chrome应用程序还是扩展程序?我的意思是,是否可能在扩展程序中有一个本地消息传递示例? - Hosein Aqajani
@H.Aqjn 在这种情况下,它是一个扩展! - rohitvk
@H.Aqjn 本地消息传递与npapi/npruntime插件的作用有些类似,即提供一种“走出”浏览器限制并实现其他功能的方式。但是,本地消息传递并不是npapi/npruntime的直接替代品,因为它只提供了该类型功能的子集。本地消息传递(作为API)可被Chrome扩展和Chrome应用程序使用,以发送和接收来自实现通信协议的外部应用程序的数据。 - bkdc

2
这对我有效:
 int main(int argc, char* argv[])
 {

 std::cout.setf( std::ios_base::unitbuf ); //instead of "<< eof" and "flushall"
 unsigned int a, c, i, t=0;
 std::string inp;  

 do {

 inp="";
 t=0;
 // Sum the first 4 chars from stdin (the length of the message passed).
  for (i = 0; i <= 3; i++) {
    t += getchar();
  }

  // Loop getchar to pull in the message until we reach the total
  //  length provided.
  for (i=0; i < t; i++) {
    c = getchar();
    inp += c;
  }

//Collect the length of the message
unsigned int len = inp.length();
//// We need to send the 4 btyes of length information
std::cout << char(((len>>0) & 0xFF))
          << char(((len>>8) & 0xFF))
          << char(((len>>16) & 0xFF))
          << char(((len>>24) & 0xFF));
//// Now we can output our message
std::cout << inp;
}

...


谢谢啊!它起作用了!通过添加 std::cout.setf(std::ios_base::unitbuf); [如果我错了请纠正] 在 std::cout 后面需要一个 EOF,对吗? - rohitvk
太好了!不,你不需要一个“eof”。 “std::ios_base::unitbuf”:每次插入操作后刷新输出。 - Marc
5
@Marc,你用来读取消息长度的代码是错误的:将字节值相加并不能得到正确的长度。请考虑使用我在回答中提供的解决方案或在Chromium扩展论坛中查看更多细节,并修改你的回答。 - bkdc
亲爱的@Marc,我有一个问题:本地消息传递的类型是什么?它是Chrome应用程序还是扩展程序? - Hosein Aqajani

0
字符串长度解码算法不正确。以下是更正内容:
for (i = 0; i <= 3; i++) {
    c = getchar();
    l |= (c << 8*i);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接