Boost :: asio tcp async_read never returns

I am trying to convert some existing code to use asio tcp boost sockets instead of the current implementation. I can get a very similar example ( chat client / server ) from the boost working site, but when I try to put the code in my own program, it stops working.

What am I doing:

  • Start the server process.
  • The server process creates an empty socket and uses it to listen (using tcp :: acceptor) for TCP connections on the port (for example, 10010)
  • Start the client process
  • Ask the client process to create a socket to connect to the server port.
  • When the server sees the client’s connection, it starts listening to data (using async_read) on the socket and creates another empty socket to listen on another TCP connection on the port
  • When the client sees that the server is connected, it sends 100 bytes of data (using async_write) and waits until the socket says that the transfer is complete ... when this happens, it prints a message and turns off
  • When the server receives a notification that it has data that has been read, it prints a message and exits

, , , , -, . , . , .., , , .

, , .

Connection.hpp:


#ifndef CONNECTION_HPP
#define CONNECTION_HPP
#include 
#include 
#include 

class ConnectionTransfer
{
public:
   ConnectionTransfer(char* buffer, unsigned int size) :
      buffer_(buffer), size_(size)   {
   }
   virtual ~ConnectionTransfer(void){}

   char* GetBuffer(){return buffer_;}
   unsigned int GetSize(){return size_;}

   virtual void CallbackForFinished() = 0;

protected:
   char* buffer_;
   unsigned int size_;
};

class ConnectionTransferInProgress
{
public:
   ConnectionTransferInProgress(ConnectionTransfer* ct):
      ct_(ct)
   {}
   ~ConnectionTransferInProgress(void){}

   void operator()(const boost::system::error_code& error){Other(error);}
   void Other(const boost::system::error_code& error){
      if(!error)
         ct_->CallbackForFinished();
   }
private:
   ConnectionTransfer* ct_;
};

class Connection 
{
public:
   Connection(boost::asio::io_service& io_service):
   sock_(io_service)
   {}
   ~Connection(void){}
   void AsyncSend(ConnectionTransfer* ct){
      ConnectionTransferInProgress tip(ct);
      //sock_->async_send(boost::asio::buffer(ct->GetBuffer(), 
      //   static_cast(ct->GetSize())), tip);
      boost::asio::async_write(sock_, boost::asio::buffer(ct->GetBuffer(), 
         static_cast(ct->GetSize())), boost::bind(
         &ConnectionTransferInProgress::Other, tip, boost::asio::placeholders::error));
   }
   void AsyncReceive(ConnectionTransfer* ct){
      ConnectionTransferInProgress tip(ct);
      //sock_->async_receive(boost::asio::buffer(ct->GetBuffer(), 
      //   static_cast(ct->GetSize())), tip);
      boost::asio::async_read(sock_, boost::asio::buffer(ct->GetBuffer(), 
         static_cast(ct->GetSize())), boost::bind(
         &ConnectionTransferInProgress::Other, tip, boost::asio::placeholders::error));
   }

   boost::asio::ip::tcp::socket& GetSocket(){return sock_;}
private:
   boost::asio::ip::tcp::socket sock_;
};
#endif //CONNECTION_HPP

BoostConnectionClient.cpp:


#include "Connection.hpp"

#include 
#include 
#include 
#include 

using namespace boost::asio::ip;

bool connected;
bool gotTransfer; 

class FakeTransfer : public ConnectionTransfer
{
public:
   FakeTransfer(char* buffer, unsigned int size) : ConnectionTransfer(buffer, size)
   {
   }
   void CallbackForFinished()
   {
      gotTransfer = true;
   }
};

void ConnectHandler(const boost::system::error_code& error)
{
   if(!error)
      connected = true;
}

int main(int argc, char* argv[])
{
   connected = false;
   gotTransfer = false;

   boost::asio::io_service io_service;

   Connection* conn = new Connection(io_service);

   tcp::endpoint ep(address::from_string("127.0.0.1"), 10011);
   conn->GetSocket().async_connect(ep, ConnectHandler);

   boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));

   while(!connected)
   {
      boost::this_thread::sleep(boost::posix_time::millisec(1));
   }
   std::cout (angle brackets here) "Connected\n";

   char data[100];
   FakeTransfer* ft = new FakeTransfer(data, 100);
   conn->AsyncReceive(ft);

   while(!gotTransfer)
   {
      boost::this_thread::sleep(boost::posix_time::millisec(1));
   }

   std::cout (angle brackets here) "Done\n";

   return 0;
}

BoostConnectionServer.cpp:


#include "Connection.hpp"

#include 
#include 
#include 
#include 

using namespace boost::asio::ip;

Connection* conn1;
bool conn1Done;
bool gotTransfer;
Connection* conn2;

class FakeAcceptor
{
public:
   FakeAcceptor(boost::asio::io_service& io_service, const tcp::endpoint& endpoint)
      : 
      io_service_(io_service),
      acceptor_(io_service, endpoint)
  {
      conn1 = new Connection(io_service_);
      acceptor_.async_accept(conn1->GetSocket(),  
         boost::bind(&FakeAcceptor::HandleAccept, this, conn1, 
         boost::asio::placeholders::error));
   }
   void HandleAccept(Connection* conn, const boost::system::error_code& error)
   {
      if(conn == conn1)
         conn1Done = true;
      conn2 = new Connection(io_service_);
      acceptor_.async_accept(conn2->GetSocket(),  
         boost::bind(&FakeAcceptor::HandleAccept, this, conn2, 
         boost::asio::placeholders::error));
   }
   boost::asio::io_service& io_service_;
   tcp::acceptor acceptor_;
};

class FakeTransfer : public ConnectionTransfer
{
public:
   FakeTransfer(char* buffer, unsigned int size) : ConnectionTransfer(buffer, size)
   {
   }
   void CallbackForFinished()
   {
      gotTransfer = true;
   }
};

int main(int argc, char* argv[])
{
   boost::asio::io_service io_service;
   conn1Done = false;
   gotTransfer = false;
   tcp::endpoint endpoint(tcp::v4(), 10011);
   FakeAcceptor fa(io_service, endpoint);
   boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service));

   while(!conn1Done)
   {
      boost::this_thread::sleep(boost::posix_time::millisec(1));
   }
   std::cout (angle brackets here) "Accepted incoming connection\n";

   char data[100];
   FakeTransfer* ft = new FakeTransfer(data, 100);
   conn1->AsyncReceive(ft);

   while(!gotTransfer)
   {
      boost::this_thread::sleep(boost::posix_time::millisec(1));
   }
   std::cout (angle brackets here) "Success!\n";
   return 0;
}

, . , , - , .

!

+3
1

ConnectHandler() , , io_service. async_connect() , io_service; , ConnectHandler(), io_service. , io_service.run() , .

conn->AsyncReceive() ConnectHandler(), async_read() ConnectHandler() , , io_service.run() .

, - io_service:: work io_service:: run ( io_service.run()):

...
// some point in the main() method, prior to creating the background thread
boost::asio::io_service::work work(io_service)
...

io_service:

io_service

, , io_service(), . , io_service , . run() io_service:: work:

http://www.boost.org/doc/libs/1_43_0/doc/html/boost_asio/reference/io_service.html

+2

Source: https://habr.com/ru/post/1736202/


All Articles