문제

직렬 포트의 장치에서 Boost :: Asio를 사용하여 Boost :: Asio를 사용하려고합니다. 부스트 :: asio : read () 및 boost :: asio :: serial_port :: read_some () 블록이 없을 때. 대신이 조건을 감지하고 장치를 시작하기 위해 포트에 명령을 작성하고 싶습니다.

사용 가능한 데이터가 없음을 어떻게 감지 할 수 있습니까?

필요한 경우 모든 것을 비동기 적으로 할 수 있습니다. 가능하다면 추가 복잡성을 피할 수 있습니다.

도움이 되었습니까?

해결책

실제로 몇 가지 옵션이 있습니다. 직렬 포트의 내장을 사용할 수 있습니다 async_read_some 함수 또는 독립형 기능을 사용할 수 있습니다 boost::asio::async_read (또는 async_read_some).

(1) 데이터를 읽거나 (2) 오류가 발생하지 않으면 콜백을 호출하지 않기 때문에 효과적으로 "차단 된"상황이 계속 발생합니다. 이 문제를 해결하려면 사용하고 싶을 것입니다. deadline_timer 타임 아웃을 설정하려면 개체. 시간 초과가 먼저 발생하면 데이터를 사용할 수 없었습니다. 그렇지 않으면 읽기 데이터가 있습니다.

추가 된 복잡성이 실제로 그렇게 나쁘지는 않습니다. 당신은 비슷한 동작을 가진 두 개의 콜백으로 끝날 것입니다. "읽기"또는 "타임 아웃"콜백이 오류가 발생하는 경우 레이스 패자라는 것을 알 수 있습니다. 오류없이 해고되면 레이스 승자라는 것을 알 수 있습니다 (그리고 다른 전화를 취소해야합니다). 당신이 차단 전화를 가졌을 곳에서 read_some, 당신은 이제 전화를 걸 것입니다 io_svc.run(). 귀하의 기능은 호출 할 때 이전과 같이 여전히 차단됩니다. run, 그러나 이번에는 지속 시간을 제어합니다.

예는 다음과 같습니다.

void foo()
{
  io_service     io_svc;
  serial_port    ser_port(io_svc, "your string here");
  deadline_timer timeout(io_svc);
  unsigned char  my_buffer[1];
  bool           data_available = false;

  ser_port.async_read_some(boost::asio::buffer(my_buffer),
      boost::bind(&read_callback, boost::ref(data_available), boost::ref(timeout),
                  boost::asio::placeholders::error,
                  boost::asio::placeholders::bytes_transferred));
  timeout.expires_from_now(boost::posix_time::milliseconds(<<your_timeout_here>>));
  timeout.async_wait(boost::bind(&wait_callback, boost::ref(ser_port),
                  boost::asio::placeholders::error));

  io_svc.run();  // will block until async callbacks are finished

  if (!data_available)
  {
    kick_start_the_device();
  }
}

void read_callback(bool& data_available, deadline_timer& timeout, const boost::system::error_code& error, std::size_t bytes_transferred)
{
  if (error || !bytes_transferred)
  {
    // No data was read!
    data_available = false;
    return;
  }

  timeout.cancel();  // will cause wait_callback to fire with an error
  data_available = true;
}

void wait_callback(serial_port& ser_port, const boost::system::error_code& error)
{
  if (error)
  {
    // Data was read and this timeout was canceled
    return;
  }

  ser_port.cancel();  // will cause read_callback to fire with an error
}

그것은 당신의 특정 요구에 맞게 여기저기서 몇 가지 조정만으로 시작해야합니다. 이게 도움이 되길 바란다!

또 다른 참고 사항 : 콜백을 처리하기 위해 추가 스레드가 필요하지 않았습니다. 모든 것이 전화 내에서 처리됩니다 run(). 이미 알고 있는지 확실하지 않습니다 ...

다른 팁

실제로 여기서 답이 암시 한 것보다 훨씬 간단하며 동기식으로 수행 할 수 있습니다.

차단 읽기가 다음과 같은 것이라고 가정합니다.

size_t len = socket.receive_from(boost::asio::buffer(recv_buf), sender_endpoint);

그런 다음 그것을 교체합니다

socket.non_blocking(true);
size_t len = 0;
error = boost::asio::error::would_block;
while (error == boost::asio::error::would_block)
    //do other things here like go and make coffee
    len = socket.receive_from(boost::asio::buffer(recv_buf), sender_endpoint, 0, error);
std::cout.write(recv_buf.data(), len);

거의 모든 보내기/수신 방법이 가지고있는 대체 과부하 형식의 수신자 _from을 사용합니다. 불행히도 깃발 논쟁을 취하지 만 0은 잘 작동하는 것 같습니다.

무료 기능 asio :: async_read를 사용해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top