boost::asio async_read/async_send 正在绕过它的处理程序

发布于 11-14 03:49 字数 5672 浏览 5 评论 0原文

我做了一个静态库。 中创建了这三个类

我在Connection Class

#ifndef _CONNECTION_H_
#define _CONNECTION_H_

#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
#include <memory>
#include "ByteBuffer.h"

class Connection: public boost::enable_shared_from_this<Connection>
{
public:
  typedef boost::shared_ptr<Connection> pointer;

  explicit Connection(boost::asio::io_service& io_service);
  virtual ~Connection();
  boost::asio::ip::tcp::socket& socket();

  virtual void OnConnected()=0;
  virtual void Send(std::shared_ptr<uint8_t> buffer, int length);
  void Receive();
  void Disconnect();
  bool connected;
protected:
  virtual void OnReceived(ByteBuffer &b) = 0;

private:
  void handle_Receive(const boost::system::error_code& error, std::size_t bytes_transferred );
  void handle_Send(const boost::system::error_code& error, std::size_t bytes_transferred);

  boost::asio::ip::tcp::socket socket_;
  bool disconnecting;
  boost::array<uint8_t, 1000> read_buffer_;
};

#endif


#include "Connection.h"


Connection::Connection(boost::asio::io_service& io_service)
    :socket_(io_service),disconnecting(false),connected(false){}

Connection::~Connection(){}


boost::asio::ip::tcp::socket& Connection::socket(){
    return socket_;
}

void Connection::Send(std::shared_ptr<uint8_t> buf, int length){
    boost::asio::async_write(socket_,boost::asio::buffer(buf.get(),length),
            boost::bind(&Connection::handle_Send, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}

void Connection::handle_Send(const boost::system::error_code& error, std::size_t bytes_transferred){

}

void Connection::Receive(){
     boost::asio::async_read(socket_,boost::asio::buffer(this->read_buffer_),
        boost::bind(&Connection::handle_Receive, shared_from_this(),boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));
}

void Connection::handle_Receive(const boost::system::error_code& error, std::size_t bytes_transferred)
{
  if(!error)
  {
      if(bytes_transferred <=0){
            this->Disconnect();
      }else{

ByteBuffer b((std::shared_ptr)this->read_buffer_.data(), this->read_buffer_.size()); this->OnReceived(b); 这->接收();} }
服务器

void Connection::Disconnect()
{
    if (!disconnecting) {
        boost::system::error_code ec;
        socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_send,ec);
        socket_.close(ec);
        disconnecting = true;
        std::cout<<"disconnected"<<std::endl;
    }
}

ConnectionFactory 类

#pragma once
#include "Connection.h"
class ConnectionFactory
{
public:
    ConnectionFactory(void);
    virtual ~ConnectionFactory(void);

    virtual Connection::pointer create(boost::asio::io_service& io_service) = 0;
};


#include "ConnectionFactory.h"


ConnectionFactory::ConnectionFactory(void)
{
}


ConnectionFactory::~ConnectionFactory(void)
{
}

#ifndef _SERVER_H_
#define _SERVER_H_

#include "Connection.h"
#include "ConnectionFactory.h"

class Server
{
public:
  Server(boost::asio::io_service& io_service , std::string ip,short port,boost::shared_ptr<ConnectionFactory> factory);
  ~Server();    
private:
  void start_accept();
  void handle_accept(boost::shared_ptr<Connection> conn,const boost::system::error_code& error);

  boost::shared_ptr<ConnectionFactory> m_factory;
  boost::asio::io_service &io_service;
  boost::asio::ip::tcp::acceptor acceptor_;
};

#endif

#include "Server.h"


Server::Server(boost::asio::io_service& io_service,std::string ip,short port,boost::shared_ptr<ConnectionFactory> factory)
    :io_service(io_service), acceptor_(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4::from_string(ip.data()), port)){

        m_factory = factory;
        start_accept();

        std::cout<<"Socket accepting connections..."<<std::endl;
}

Server::~Server()
{
}


void Server::start_accept(){

    boost::shared_ptr<Connection> conn = m_factory->create(this->io_service);
    acceptor_.async_accept(conn->socket(),
        boost::bind(&Server::handle_accept, this,conn,boost::asio::placeholders::error));

}


void Server::handle_accept(boost::shared_ptr<Connection> conn,const boost::system::error_code& error){
    if (!error){
        std::cout<<"on connected"<<std::endl;
        conn->OnConnected();
        conn->Receive();
        start_accept();
    }
    //conn->Disconnect();
}

,我从静态库中获取并使用了这些类,它

在我的 main.cpp 中

#include <iostream>
#include "auth_proto.h"
#include <Server.h>
#include <ConnectionFactory.h>
#include "AuthConnectionFactory.h"

using namespace std;
int main()
{
    Auth_Setup();
  try
  {
      boost::asio::io_service io_service;
      boost::shared_ptr<ConnectionFactory> fact (new AuthConnectionFactory(io_service));
      Server s(io_service,"5.113.195.156",9959,fact);
      io_service.run();
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }

  return 0;
}

工作得很好,我真的不明白这里出了什么问题,当涉及到 Receive() 函数时,它正在接收数据来自客户端,但它不会调用handle_Receive()方法,因此我可以使用这些数据,等待它应该调用handle_Receive()的行为,以便我可以将数据传递给ByteBuffer并使用它,但这并没有发生.. ....

I made a static-lib. And I created this three classes in

Connection Class

#ifndef _CONNECTION_H_
#define _CONNECTION_H_

#include <boost/array.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>
#include <memory>
#include "ByteBuffer.h"

class Connection: public boost::enable_shared_from_this<Connection>
{
public:
  typedef boost::shared_ptr<Connection> pointer;

  explicit Connection(boost::asio::io_service& io_service);
  virtual ~Connection();
  boost::asio::ip::tcp::socket& socket();

  virtual void OnConnected()=0;
  virtual void Send(std::shared_ptr<uint8_t> buffer, int length);
  void Receive();
  void Disconnect();
  bool connected;
protected:
  virtual void OnReceived(ByteBuffer &b) = 0;

private:
  void handle_Receive(const boost::system::error_code& error, std::size_t bytes_transferred );
  void handle_Send(const boost::system::error_code& error, std::size_t bytes_transferred);

  boost::asio::ip::tcp::socket socket_;
  bool disconnecting;
  boost::array<uint8_t, 1000> read_buffer_;
};

#endif


#include "Connection.h"


Connection::Connection(boost::asio::io_service& io_service)
    :socket_(io_service),disconnecting(false),connected(false){}

Connection::~Connection(){}


boost::asio::ip::tcp::socket& Connection::socket(){
    return socket_;
}

void Connection::Send(std::shared_ptr<uint8_t> buf, int length){
    boost::asio::async_write(socket_,boost::asio::buffer(buf.get(),length),
            boost::bind(&Connection::handle_Send, shared_from_this(), boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}

void Connection::handle_Send(const boost::system::error_code& error, std::size_t bytes_transferred){

}

void Connection::Receive(){
     boost::asio::async_read(socket_,boost::asio::buffer(this->read_buffer_),
        boost::bind(&Connection::handle_Receive, shared_from_this(),boost::asio::placeholders::error,boost::asio::placeholders::bytes_transferred));
}

void Connection::handle_Receive(const boost::system::error_code& error, std::size_t bytes_transferred)
{
  if(!error)
  {
      if(bytes_transferred <=0){
            this->Disconnect();
      }else{

ByteBuffer b((std::shared_ptr)this->read_buffer_.data(), this->read_buffer_.size());
this->OnReceived(b);
this->Receive();}
}
}

void Connection::Disconnect()
{
    if (!disconnecting) {
        boost::system::error_code ec;
        socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_send,ec);
        socket_.close(ec);
        disconnecting = true;
        std::cout<<"disconnected"<<std::endl;
    }
}

ConnectionFactory class

#pragma once
#include "Connection.h"
class ConnectionFactory
{
public:
    ConnectionFactory(void);
    virtual ~ConnectionFactory(void);

    virtual Connection::pointer create(boost::asio::io_service& io_service) = 0;
};


#include "ConnectionFactory.h"


ConnectionFactory::ConnectionFactory(void)
{
}


ConnectionFactory::~ConnectionFactory(void)
{
}

Server Class

#ifndef _SERVER_H_
#define _SERVER_H_

#include "Connection.h"
#include "ConnectionFactory.h"

class Server
{
public:
  Server(boost::asio::io_service& io_service , std::string ip,short port,boost::shared_ptr<ConnectionFactory> factory);
  ~Server();    
private:
  void start_accept();
  void handle_accept(boost::shared_ptr<Connection> conn,const boost::system::error_code& error);

  boost::shared_ptr<ConnectionFactory> m_factory;
  boost::asio::io_service &io_service;
  boost::asio::ip::tcp::acceptor acceptor_;
};

#endif

#include "Server.h"


Server::Server(boost::asio::io_service& io_service,std::string ip,short port,boost::shared_ptr<ConnectionFactory> factory)
    :io_service(io_service), acceptor_(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4::from_string(ip.data()), port)){

        m_factory = factory;
        start_accept();

        std::cout<<"Socket accepting connections..."<<std::endl;
}

Server::~Server()
{
}


void Server::start_accept(){

    boost::shared_ptr<Connection> conn = m_factory->create(this->io_service);
    acceptor_.async_accept(conn->socket(),
        boost::bind(&Server::handle_accept, this,conn,boost::asio::placeholders::error));

}


void Server::handle_accept(boost::shared_ptr<Connection> conn,const boost::system::error_code& error){
    if (!error){
        std::cout<<"on connected"<<std::endl;
        conn->OnConnected();
        conn->Receive();
        start_accept();
    }
    //conn->Disconnect();
}

and I drevid from the static-lib and used this classes and it's working perfect

in my main.cpp

#include <iostream>
#include "auth_proto.h"
#include <Server.h>
#include <ConnectionFactory.h>
#include "AuthConnectionFactory.h"

using namespace std;
int main()
{
    Auth_Setup();
  try
  {
      boost::asio::io_service io_service;
      boost::shared_ptr<ConnectionFactory> fact (new AuthConnectionFactory(io_service));
      Server s(io_service,"5.113.195.156",9959,fact);
      io_service.run();
  }
  catch (std::exception& e)
  {
    std::cerr << e.what() << std::endl;
  }

  return 0;
}

I really don't understand what is wrong here , when it comes to the Receive() function it's receive the data from the client but it does not invoking the handle_Receive() method so I can use this data, the behavior that am waiting that it should call the handle_Receive() so I can pass the data to ByteBuffer and use it but that's not happening ......

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不气馁2024-11-21 03:49:43

boost::asio::async_read 似乎仅在达到传递给它的“数据量”时才调用读取处理程序。

引用boost的1.46.0参考:

异步读取

启动异步操作以从流中读取一定量的数据。

因此,作为解决方案,如果您希望了解收到的任意数量的数据,请使用 socket_.async_read_some 而不是 boost::asio::async_read

另一种解决方案,正如 Sam Miller 在评论中试图说的那样,您可以添加一个固定大小的标头,其中包含您应该接收的每个帧之前传入的字节数,读取标头然后调用 boost::asio: :async_read 与之前提取的数字。

boost::asio::async_read seems to call the read handler only when it reaches the "amount of data" passed to it.

Quoting boost's 1.46.0 reference:

async_read

Start an asynchronous operation to read a certain amount of data from a stream.

So as a solution, use socket_.async_read_some instead of boost::asio::async_read if you wish to be informed of any arbitrary amount of data received.

Another solution, as Sam Miller was trying to say in the comments, you can add a fixed size header containing the number of bytes incoming before each frame you're supposed to receive, read the header then call boost::asio::async_read with the previously extracted number.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文