首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何丢弃以boost::asio发送的数据?

如何丢弃以boost::asio发送的数据?
EN

Stack Overflow用户
提问于 2014-03-22 17:51:14
回答 1查看 6.1K关注 0票数 5

我正在编写一些使用boost::asio类读写串行设备的代码。然而,当在程序之间发送几个字符串时,我注意到在接收程序中,数据是按照写入串口的顺序读取的,而不是从其他程序发送的数据--如果几秒钟后我开始读取数据,我就不会得到当前发送的值,而是以前发送的值。我假设这是我设置boost::asio::serial_port的方式造成的

代码语言:javascript
运行
复制
int main(int argc, char const *argv[]){

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

    printf("Virtual device: %s\n",pty.data());
    printf("Baud rate: %d\n",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;
}

在将新值发送到串行端口(我认为应该在代码的写()部分上完成)时,是否有一种方法强制丢弃过去的数据?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-03-23 23:04:06

Boost.Asio不提供用于刷新串口缓冲区的更高级别的抽象。但是,这通常可以通过让特定于平台的调用(如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个数字,睡眠5秒,并每隔一次迭代刷新其读取缓冲区:

代码语言:javascript
运行
复制
#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创建虚拟串口

代码语言:javascript
运行
复制
$ 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]

开始读和写示例:

代码语言:javascript
运行
复制
$ ./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时,才会在序列中跳过数字。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22581315

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档