workflow自定义协议如何分包发送消息
oceanfan1990 opened this issue · comments
现在有一个场景如下:
1.利用workflow自定义了一个通信协议,协议不仅是一发一收,可以是一发多收;
如:客户端发送 数据请求,发送报文如下: 0a 00 00 00 00 00;
服务端需要发送数据回复,发送报文如下 :a. 0b 00 00 00 00 00; b. 0a 00 00 00 00 ...
即是客户端发送了 数据请求, 服务端需要首先回复 数据确认报文a, 然后再回复数据应答报文b.
如果数据应答报文的长度过长,还需要进行固定长度的分割,再分包发送;
我参考了一下workflow的文档,我自己的做法如下,但是有问题:贴出代码如下:
//just for test
void timer_callback(WFTimerTask *timer)
{
printf("Finished. Press enter to end.\n");
SeriesWork *series = series_of(timer);
dl476_series_context *context = (dl476_series_context *)series->get_context();
auto *proxy_resp = context->dl476_task->get_resp();
int into = context->into;
std::string filename = context->filename;
int filename_size = filename.size();
int err = -1;
if(err == -1) //NOTE 文件没有更新
{
int size = 23 + filename_size + 1;
int time = 1721284510; //
uint8 * cacheBuf = (uint8 *)malloc(size);
if(!cacheBuf)
return;
int len = 17 + filename_size;
cacheBuf[0] = A_DATA; //控制域 不需要扩展
cacheBuf[1] = 0; //运行模式,0型规程,00010000
cacheBuf[2] = 0; //状态标识
cacheBuf[3] = 0; //原因码
cacheBuf[4] = len % 256; //参数域长度,不需要扩充参数
cacheBuf[5] = len / 256;
cacheBuf[6] = 42;
cacheBuf[7] = 0;
int i = 8;
cacheBuf[i] = 0;
cacheBuf[++i] = 0;
cacheBuf[++i] = 0;
cacheBuf[++i] = 0;
cacheBuf[++i] = 0;
cacheBuf[++i] = 0;
cacheBuf[++i] = 0;
cacheBuf[++i] = 0;
//时间赋值
util::timedecode(&cacheBuf[++i], time);
i += 7;
memcpy(&cacheBuf[i], filename.data(), filename_size);
i += filename_size;
proxy_resp->set_message_body(cacheBuf, i);
free(cacheBuf);
}
else if(err == 0) //NOTE 文件有更新
{
std::string t_file = "util.cc";
std::string t_filetext;
std::size_t t_filesize;
util util_obj;
t_filesize = util_obj.readfiletostring(t_file, t_filetext);
}
delete (dl476_series_context *)series->get_context();
}
void process(WFDl476Task *task)
{
printf("address %x\n", task);
//获取客户端ip信息,如果客户端ip非法,则断开连接
std::string ipstr;
int port;
util::getipinfofromtask(task, ipstr, port);
auto search = g_ipset.find(ipstr);
if(search == g_ipset.end())
{
printf("illegal client ip : %s, port : %d server will close it\n", ipstr.data(), port);
task->set_keep_alive(1 * 1000);
}
Dl476Request *req = task->get_req();
Dl476Response *resp = task->get_resp();
uint8 *body;
size_t size;
req->get_message_body_size(&size);
printf("size : %ld\n", size);
body = (uint8 *)malloc(size);
req->get_message_body_nocopy(&body, size);
struct RequestInfo reqinfo;
int ret = resp->message_body_parser(body, size, reqinfo);
if(ret == 1) //NOTE 约定: 返回值0代表非数据请求, 1代表数据请求
{
resp->dl476_dataack_reply(A_DATA_ACK); //TODO 收到数据请求,首先回复数据确认
task->set_callback([&, reqinfo](WFDl476Task *server_task){
//获取上下文,执行异步任务,并且把异步任务获取的结果返回
SeriesWork *series = series_of(server_task);
dl476_series_context *context = new dl476_series_context;
context->dl476_task = task;
context->into = reqinfo.into;
context->filename = reqinfo.filename;
series->set_context(context);
switch (reqinfo.type)
{
case RequestType::ftp :
{
//just for test
WFTimerTask *timer = WFTaskFactory::create_timer_task(1000000, timer_callback);
series->push_back(timer);
}
break;
case RequestType::display :
{
}
break;
case RequestType::stopdata :
{
}
break;
default:
break;
}
// delete (dl476_series_context *)series->get_context();
});
}
free(body);
printf("\nexist process\n");
}
这样做,是可以首先发送数据确认报文了,但是数据应答报文却发送不出了;是不是因为 进入callback之后,原本的task的生命期就结束了,所以timer_callback中获取到series中的task不是原来的task,导致发送不出?
我要怎么样做才能做到服务端可以分包发送回复?而且分包的大小可以调整?
或许这个问题可以利用task的push接口;测试代码可以改为:
uint8 cacheBuf[4];
cacheBuf[0] = A_DATA_ACK; //控制域 不需要扩展
cacheBuf[1] = 0;
cacheBuf[2] = 0;
cacheBuf[3] = 0;
task->push(&cacheBuf, 4);
cacheBuf[0] = A_DATA_NAK; //控制域 不需要扩展
cacheBuf[1] = 0;
cacheBuf[2] = 0;
cacheBuf[3] = 0;
task->push(&cacheBuf, 4);
用task的push接口测试了一下,可以达到分包发送的效果;收到数据请求后,首先push一下数据确认报文,然后得到数据应答报文,分割后再调用push接口逐一发送
噢噢,你用push接口的话,要维护server_task的生命周期,只需要在series里push_back一个counter任务,直到结束时,调用counter->count()接口打开就可以了。例如:
void process(WFHttpTask *task)
{
WFCounterTask *counter = WFTaskFactory::create_counter_task(1, nullptr);
series_of(task)->push_back(task);
task->noreply();
WFTimerTask *timer = WFTaskFactory::create_timer_task(1, 0, [task, counter](WFTimerTask *timer) {
task->push(...);
counter->count();
});
timer->start();
}
不过,这个case下,其实也不需要用counter,你把timer push_back到series里就可以了。只有series不结束,server_task并不会运行到callback。
void process(WFHttpTask *task)
{
task->noreply();
WFTimerTask *timer = WFTaskFactory::create_timer_task(1, 0, [task](WFTimerTask *timer) {
task->push(...);
});
series_of(task)->push_back(timer);
}
@Barenboim 我参考一下