加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 如何丢弃与boost :: asio一起发送的数据?

发布时间:2020-12-16 09:51:16 所属栏目:百科 来源:网络整理
导读:我正在编写一些使用boost :: asio类读取和写入串行设备的代码.但是,当在程序之间发送多个字符串时,我注意到在接收程序中,数据在写入串口时按顺序读取,而不是从其他程序发送数据 – 如果我开始读取数秒之后的数据,我不会得到我现在发送的值,而是之前发送的值.
我正在编写一些使用boost :: asio类读取和写入串行设备的代码.但是,当在程序之间发送多个字符串时,我注意到在接收程序中,数据在写入串口时按顺序读取,而不是从其他程序发送数据 – 如果我开始读取数秒之后的数据,我不会得到我现在发送的值,而是之前发送的值.我假设这是由我如何设置我的boost :: asio :: serial_port引起的:

int main(int argc,char const *argv[]){

    int baud=atoi(argv[1]);
    std::string pty=argv[2];

    printf("Virtual device: %sn",pty.data());
    printf("Baud rate: %dn",baud);

    boost::asio::io_service io;
    boost::asio::serial_port port(io,pty);
    port.set_option(boost::asio::serial_port_base::baud_rate(baud));

    // counter that writes to serial port in 1s intervals
    int val=0;
    while (1){
        std::string data=std::to_string(val);
        data+='n';
        std::cout << data;
        write(port,boost::asio::buffer(data.c_str(),data.size()));
        sleep(1); 
        val++;
        data.clear();
    }

    port.close(); 
    return 0;
}

有一种方法可以在将新值发送到串行端口时强制将过去的数据丢弃(我假设应该在代码的write()部分完成)?

解决方法

Boost.Asio没有为刷新串口缓冲区提供更高级别的抽象.但是,这通常可以通过在串行端口 native_handle()上运行特定于平台的调用(例如 tcflush()PurgeComm())来实现.

每个串行端口都有一个接收和发送缓冲区,并且刷新操作在一个或两个缓冲区上.例如,如果连接了两个串行端口(/ dev / pts / 3和/ dev / pts / 4),并且程序A打开并写入/ dev / pts / 3,则它只能刷新与/ dev关联的缓冲区/ pts / 3(在/ dev / pts / 3上接收但未读取的数据,以及写入/ dev / pts / 3但未传输的数据).因此,如果程序B启动,打开/ dev / pts / 4,并且想要读取非陈旧数据,则程序B需要在打开串口后刷新/ dev / pts / 4的接收缓冲区.

这是在CentOs上运行的完整示例.当示例作为编写器运行时,它将每秒向串行端口写入一个按顺序递增的数字.当示例作为编写器运行时,它将读取五个数字,休眠5秒并每隔一次迭代刷新其读取缓冲区:

#include <iostream>
#include <vector>
#include <boost/asio.hpp>
#include <boost/thread.hpp>

/// @brief Different ways a serial port may be flushed.
enum flush_type
{
  flush_receive = TCIFLUSH,flush_send = TCOFLUSH,flush_both = TCIOFLUSH
};

/// @brief Flush a serial port's buffers.
///
/// @param serial_port Port to flush.
/// @param what Determines the buffers to flush.
/// @param error Set to indicate what error occurred,if any.
void flush_serial_port(
  boost::asio::serial_port& serial_port,flush_type what,boost::system::error_code& error)
{
  if (0 == ::tcflush(serial_port.lowest_layer().native_handle(),what))
  {
    error = boost::system::error_code();
  }
  else
  {
    error = boost::system::error_code(errno,boost::asio::error::get_system_category());
  }
}

/// @brief Reads 5 numbers from the serial port,then sleeps for 5 seconds,///        flushing its read buffer every other iteration.
void read_main(boost::asio::serial_port& serial_port)
{
  std::vector<unsigned char> buffer(5);
  for (bool flush = false;; flush = !flush)
  {
    std::size_t bytes_transferred =
        read(serial_port,boost::asio::buffer(buffer));
    for (std::size_t i = 0; i < bytes_transferred; ++i)
      std::cout << static_cast<unsigned int>(buffer[i]) << " ";
    boost::this_thread::sleep_for(boost::chrono::seconds(5));
    if (flush)
    {
      boost::system::error_code error;
      flush_serial_port(serial_port,flush_receive,error);
      std::cout << "flush: " << error.message() << std::endl;
    }
    else
    {
      std::cout << "noflush" << std::endl;
    }
  }
}

/// @brief Write a sequentially increasing number to the serial port
///        every second.
void write_main(boost::asio::serial_port& serial_port)
{
  for (unsigned char i = 0; ; ++i)
  {
    write(serial_port,boost::asio::buffer(&i,sizeof i));
    boost::this_thread::sleep_for(boost::chrono::seconds(1));
  }
}

int main(int argc,char* argv[])
{
  boost::asio::io_service io_service;
  boost::asio::serial_port serial_port(io_service,argv[2]);
  if (!strcmp(argv[1],"read"))
    read_main(serial_port);
  else if (!strcmp(argv[1],"write"))
    write_main(serial_port);
}

使用socat创建虚拟串行端口:

$socat -d -d PTY: PTY:
2014/03/23 16:22:22 socat[12056] N PTY is /dev/pts/3
2014/03/23 16:22:22 socat[12056] N PTY is /dev/pts/4
2014/03/23 16:22:22 socat[12056] N starting data transfer loop with
                                 FDs [3,3] and [5,5]

启动读写示例:

$./a.out read /dev/pts/3 & ./a.out write /dev/pts/4
[1] 12238
0 1 2 3 4 noflush
5 6 7 8 9 flush: Success
14 15 16 17 18 noflush
19 20 21 22 23 flush: Success
28 29 30 31 32 noflush
33 34 35 36 37 flush: Success

如在输出中所示,当读取器刷新其读取缓冲器时,仅在序列中跳过数字:3 4 noflush 5 6 7 8 9 flush 14 15.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读