async_ read_until无法按预期工作

时间:2015-11-18 23:19:15

标签: string sockets boost tcp boost-asio

所以我试图编写一个通过tcp套接字读写数据的程序。我可以成功接受连接,向它写入数据(虽然写处理程序不能按预期工作?)。我也想通过相同的套接字读取数据 - 这似乎不起作用。 处理所有这些的类如下:

using namespace boost::asio;
using namespace boost::asio::ip;


TcpServer::TcpServer(unsigned short port = 1700)
  : ipPort(port){
  tcp::acceptor acc(svc, tcp::endpoint(tcp::v4(), ipPort));
  acc.listen();
  acc.async_accept(socket, boost::bind(&TcpServer::Accept_Handler,this, placeholders::error));

  SAY("Waiting for a New connection");
  svc.run();
}

void TcpServer::Write_Handler(const boost::system::error_code& ec,
                  std::size_t bytes_transferred){
  std::cout << ec.message() << std::endl;
  if (!ec)
    {
      std::cout << "Just sent " << yawData << std::endl;
    }
}
void TcpServer::Read_Handler(const boost::system::error_code& ec,
                std::size_t bytes_transferred){
  if (!ec)
    {
      std::string line;
     std::istream is(&input_buffer_);
     std::string test;
     is >> test;
     std::cout << "test" << test << std::endl;
     std::getline(is, line);
     if (!line.empty())
       {
     std::cout << "Recieved: " << line << std::endl;
       }
    }
  else
    std::cout << "Error reading:" << ec.message() << std::endl;
}

void TcpServer::Accept_Handler(const boost::system::error_code& ec){
  if (!ec)
    {
      std::cout << "Accepted a connection! - Now switching to write mode " << std::endl;
  connectMode = 1;
    }
}

void TcpServer::Write_Data(){
  if (connectMode){
    SAY("Sent data");
    std::ostringstream ss;
    std::string sendBuffer;
    ss << std::fixed << std::setprecision(2);
    ss << yawData;
    sendBuffer = ss.str() + "\r";
    async_write(socket, buffer(sendBuffer),       boost::bind(&TcpServer::Write_Handler, this,
                      placeholders::error,
                       placeholders::bytes_transferred));
    }
}


void TcpServer::UpdateYaw(double data) {
  yawData = data;
}  

void TcpServer::Read_Data(){
  if (connectMode){
    async_read_until(socket, input_buffer_, "\n" ,      boost::bind(&TcpServer::Read_Handler, this,
                          placeholders::error,
                               placeholders::bytes_transferred));
  }
}

TcpServer::~TcpServer(){
   svc.stop();
}

类标题如下:

class TcpServer {
 private:
  io_service svc;  
  tcp::socket socket{svc};

  double yawData = 0;
  unsigned short ipPort;
  bool connectMode = 0;
  streambuf input_buffer_;
  void Write_Handler(const boost::system::error_code&,
             std::size_t);
  void Read_Handler(const boost::system::error_code&,
             std::size_t);
   void Accept_Handler(const boost::system::error_code&);
 public:
  TcpServer(unsigned short );
  void Write_Data();
  void Read_Data();
  void UpdateYaw(double);
  ~TcpServer();
};

要使用它,我调用Write_Data(),然后调用Read_Data()。 Write_Data有效,但写入处理程序未被调用 - 我可以在客户端接收数据。 Read_Data()根本不起作用。我确信数据是通过套接字以所需的格式发送的(以“\ n”结尾)

关于什么可能出错或任何调试技巧的想法?

由于

修改

我计划从main函数运行write_data和read_data函数,如下所示:

  TcpServer *socketObj = new TcpServer(1700);

     while ( i < 100 && trackObj->ReadTrackingState() != 0) {
      SAY("Current Yaw - %.02f", trackObj->CurrentYaw());
      socketObj->UpdateYaw(trackObj->CurrentYaw());
      socketObj->Write_Data();
      socketObj->Read_Data();
      Platform::sleepMillis(1000);
      i++;

     }

1 个答案:

答案 0 :(得分:1)

void TcpServer::Accept_Handler(const boost::system::error_code &ec) {
    if (!ec) {
        std::cout << "Accepted a connection! - Now switching to write mode " << std::endl;
        connectMode = 1;
    }
}

此功能结束异步处理。它没有安排任何更多的异步工作,因此io_service::run()结束,如文档所示。

您希望直接链接或使用io_service::work来保持服务正常运行。我建议链接:

void TcpServer::Accept_Handler(const boost::system::error_code &ec) {
    if (!ec) {
        std::cout << "Accepted a connection! - Now switching to write mode " << std::endl;
        Write_Data();
    }
}

但是......

HOLD ON

您需要仔细查看所有代码。

void TcpServer::Write_Data() {
    SAY("Sent data");
    std::ostringstream ss;
    std::string sendBuffer;
    ss << std::fixed << std::setprecision(2);
    ss << yawData;
    sendBuffer = ss.str() + "\r";
    async_write(socket, buffer(sendBuffer),
            boost::bind(&TcpServer::Write_Handler, this, placeholders::error, placeholders::bytes_transferred));
}

这里发生了什么?首先,您创建一个临时流,无法使用它来附加回车符,然后将引用传递给本地字符串async_write ......这无法正常工作。它是Undefined Behaviour

修复:

void TcpServer::Write_Data() {
    SAY("Send data");
    std::ostream ss(&output_buffer_);
    ss << std::fixed << std::setprecision(2) << yawData << "\r";
    async_write(socket, output_buffer_,
            boost::bind(&TcpServer::Write_Handler, this, placeholders::error, placeholders::bytes_transferred));
}

样本

Live On Coliru

#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <iomanip>

using namespace boost::asio;
using namespace boost::asio::ip;

template <typename T>
static inline void SAY(T&& v) { std::cout << std::forward<T>(v) << "\n"; }

class TcpServer {
  private:
    io_service svc;
    tcp::socket socket{ svc };

    double yawData = 0;
    unsigned short ipPort;
    streambuf input_buffer_, output_buffer_;

    void Write_Handler(const boost::system::error_code &, std::size_t);
    void Read_Handler(const boost::system::error_code &, std::size_t);
    void Accept_Handler(const boost::system::error_code &);

  public:
    TcpServer(unsigned short = 1700);
    void Write_Data();
    void Read_Data();
    void UpdateYaw(double);
    ~TcpServer();
};

TcpServer::TcpServer(unsigned short port) : ipPort(port) {
    tcp::acceptor acc(svc, tcp::endpoint(tcp::v4(), ipPort));
    acc.listen();
    acc.async_accept(socket, boost::bind(&TcpServer::Accept_Handler, this, placeholders::error));

    SAY("Waiting for a New connection");
    svc.run();
}

void TcpServer::Write_Handler(const boost::system::error_code &ec, std::size_t /*bytes_transferred*/) {
    std::cout << ec.message() << std::endl;
    if (!ec) {
        std::cout << "Just sent " << yawData << std::endl;
        Read_Data();
    }
}
void TcpServer::Read_Handler(const boost::system::error_code &ec, std::size_t /*bytes_transferred*/) {
    if (!ec) {
        std::cout << "Recieved: " << &input_buffer_ << std::endl;
    } else
        std::cout << "Error reading:" << ec.message() << std::endl;
}

void TcpServer::Accept_Handler(const boost::system::error_code &ec) {
    if (!ec) {
        std::cout << "Accepted a connection! - Now switching to write mode " << std::endl;
        Write_Data();
    }
}

void TcpServer::Write_Data() {
    SAY("Send data");
    std::ostream ss(&output_buffer_);
    ss << std::fixed << std::setprecision(2) << yawData << "\r";
    async_write(socket, output_buffer_,
            boost::bind(&TcpServer::Write_Handler, this, placeholders::error, placeholders::bytes_transferred));
}

void TcpServer::UpdateYaw(double data) { yawData = data; }

void TcpServer::Read_Data() {
    async_read_until(socket, input_buffer_, "\n", boost::bind(&TcpServer::Read_Handler, this, placeholders::error,
                placeholders::bytes_transferred));
}

TcpServer::~TcpServer() { svc.stop(); }

int main() {
    TcpServer server;
}