最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

在gRPC流的服务器端调用.end()之前如何在客户端接收数据

运维笔记admin13浏览0评论

在gRPC流的服务器端调用.end()之前如何在客户端接收数据

在gRPC流的服务器端调用.end()之前如何在客户端接收数据

我目前正在尝试使用gRPC Node.js API设置服务器流。为此,我想在服务器端写入流时,客户端立即接收到数据事件。

目前,如果仅在服务器端调用write,那么我在客户端什么都不会收到。但是,一旦我在服务器上调用end函数,客户端就会收到所有数据事件。

为了测试这一点,我使用了一个无尽的while循环在服务器端编写消息。然后,客户端不接收消息(数据事件)。如果相反,我使用for循环并随后调用end,则在调用end时,客户端会收到所有消息(数据事件)。

我的.proto文件:

syntax = "proto3";

message ControlMessage {
  enum Control {
    Undefined = 0;
    Start = 1;
    Stop = 2;
  }
  Control control = 1;
}

message ImageMessage {
  enum ImageType {
    Raw = 0;
    Mono8 = 1;
    RGB8 = 2;
  }
  ImageType type = 1;
  int32 width = 2;
  int32 height = 3;
  bytes image = 4;
}

service StartImageTransmission {
  rpc Start(ControlMessage) returns (stream ImageMessage);
}

在服务器端,我实现了启动功能,并尝试不断向呼叫写入消息:

function doStart(call) {
  var imgMsg = {type: "Mono8", width: 600, height: 600, image: new ArrayBuffer(600*600)};
  //for(var i = 0; i < 10; i++) {
  while(true) {
    call.write(imgMsg);
    console.log("Message sent");
  }
  call.end();
}

我将该功能注册为服务器中的服务:

var server = new grpc.Server();
server.addService(protoDescriptor.StartImageTransmission.service, {Start: doStart});

在客户端,我生成一个适当的调用并注册数据和结束事件:

var call = client.Start({control: 0});
call.on('data', (imgMessage) => {
  console.log('received image message');
});
call.read();
call.on('end', () => {console.log('end');});

我还试图用python编写服务器端。在这种情况下,节点客户端不仅在服务器端结束流传输后立即接收消息。因此,我想这对于使用Node API编写的服务器也是应该可行的。

回答如下:

似乎问题在于,无尽的while循环阻塞了节点中的所有后台任务。一种可能的解决方案是使用setTimeout创建循环。以下代码为我工作:

首先在gRPC调用中将call对象存储在数组中:

function doStart(call) {
  calls.push(call);
}

为了发送给所有客户端,我使用了setTimeout:

function sendToAllClients() {
  calls.forEach((call) => {
    call.write(imgMsg);
  });
  setTimeout(sendToAllClients, 10);
}

setTimeout(sendToAllClients, 10);

发布评论

评论列表(0)

  1. 暂无评论