gpt4 book ai didi

c++ - 如何将 socket.async_read_some 的读取处理程序调用同步到特定频率?

转载 作者:行者123 更新时间:2023-11-30 05:44:43 26 4
gpt4 key购买 nike

如何将 sock.async_read_some 的 read_handler 调用同步到特定频率,同时读取 812 字节的流(以 125 Hz 的频率流式传输)。

我有一个与从机器人读取流相关的问题。我对 boost asio 很陌生。我对这个概念知之甚少。这是我的代码中的示例 block 。 read_handler 所做的是,它处理来自机器人的数据。这个循环应该每 8 毫秒执行一次,这是我的采样时间,并且在它开始执行时,应该完成从机器人读取数据流。当我查看机器人的流数据时,数据每 8 毫秒出现一次。所以机器人数据没问题。但是 read_handler 的执行有点问题。例如,第一个循环从时间 = 0 开始,第二个循环从时间 = 2 开始,第三个循环从时间 = 16 开始,第四个循环从时间 = 18 开始,第五个循环再次从时间 = 32 开始。因此,触发时间循环的每一次从第一次变为第二次。但是在第三次它再次同步到 8 毫秒的倍数。我需要的是 read_handler 应该每 8 毫秒触发一次(当数据到达时),但它会在每两次调用(总共 16 毫秒)时捕获此采样时间。这是至关重要的,因为我正在进行计算,并在稍后将命令反馈给机器人(控制系统)。这段代码没有详细介绍发送命令等,只包含非常基本的数据处理。那么,是什么导致了调用之间的这些差异,我该如何解决?

我通过网络和堆栈溢出进行了搜索,但我无法遇到另一个与时间相关的问题。

void read_handler(const boost::system::error_code &ec, std::size_t bytes_transferred)
{

if (!ec)
{
thisLoopStart = clock();
loopInstant[iterationNum]=diffclock(startTime, endLoopTime);
std::cout << "Byte transfered: " << bytes_transferred << std::endl;
printf("Byte transfered: %d", bytes_transferred);
printf("Byte transfered: %d", bytes_transferred);
printf("Byte transfered: %d\n", bytes_transferred);
//std::cout << std::string(buffer.data(), bytes_transferred) << std::endl;
char myTempDoubleTime[8];
for (int j = 0; j<1; j++)
{
for (int i = 0; i < 8; i++ )
{
myTempDoubleTime[7-i]=buffer[4+i+8*j]; //636
}
memcpy(&controllerTime[iterationNum], myTempDoubleTime, 8);
}
endLoopTime = clock();

thisLoopDuration = diffclock(thisLoopStart, endLoopTime);

loopTimes[iterationNum] = thisLoopDuration;

if (iterationNum++>500)
{//io_service.~io_service();

//io_service.reset();
//io_service.run();
exitThread = 1;
printf("Program terminates...\n");
GlobalObjects::myFTSystem->StopAcquisition();

for(int i=1;i<iterationNum;i++)
fprintf(LoopDurations, "%f\t%f\t%f\n", loopTimes[i], controllerTime[i], loopInstant[i]);


fclose(LoopDurations);

closeConnectionToServer();
printf("Connection is closed...\n");
io_service.stop();
}
sock.async_read_some(boost::asio::buffer(buffer), read_handler);
}

}

最佳答案

如果传入流的时间由机器人本身控制,那么您就不必担心在某时某时尝试专门读取。如果您期望机器人每 X 秒爆发一次 812 字节,只需从您的客户端套接字中保持 async_reading。 boost::asio 将在读取完成后立即调用您的回调。

至于神秘的延迟,请尝试在调用 async_read_some 时明确说明缓冲区的大小,如下所示:

sock.async_read_some(boost::asio::buffer(buffer, 812), read_handler);

如果您确定您总是传输足够的数据来填充这样的缓冲区,那么这应该会导致您的回调被一致调用,因为提供给 boost::asio 的缓冲区已满。如果这不能解决您的问题,请按照 sehe 的建议执行并实现 dealine_timer您可以使用它来更好地基于时间控制您的异步操作。

编辑
您还应该检查 OnRead 处理程序中的 bytes_transferred 以确保您已从机器人进行了完整读取。现在你只是打印它。你可能有一个不完整的读取,这意味着你应该立即从套接字开始重复读取,直到你确定你已经消耗了你期望的所有数据。否则,您将尝试对不完整的数据采取行动,从而搞砸自己,很可能在那里失败,然后启动另一个 ::async_read 假设您正在开始一个干净的新读取,而实际上您是我们只是要读取您忽略并留在套接字上的旧数据,并开始对您的读取进行分段。

这可以解释为什么您会看到比预期间隔更短和更长的不一致时间。显式指定缓冲区大小并检查您在处理程序中传递的 bytes_transferred 将保证您捕获此类问题。另请查看文档,了解可以传递给::asio 的 completion_condition 类型,例如 ::transfer_exactly(num_bytes),但我不确定这些是否适用于异步读取操作。

关于c++ - 如何将 socket.async_read_some 的读取处理程序调用同步到特定频率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29647855/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com