c++ - boost 异步服务器两次接受连接

标签 c++ asynchronous boost boost-asio

我正在开发一个 boost.asio 异步服务器。 目前服务器代码非常简单。它接受来自客户端的连接,并在接受连接时向客户端发送 READY 消息。客户端打印 READY 消息,然后允许用户在客户端控制台中写入任何消息。客户端输入的任何消息都将发送到服务器。服务器打印消息和消息的字节大小,然后将相同的消息发送回带有额外“... OK”字符串的客户端。

现在我遇到的是在服务器接受连接并发送第一个“READY”消息后,它接受另一个连接并实例化新的连接类。但之后一切都按预期进行。

所以,我不太确定为什么在调用 async_write(发送 READY 消息)后它重新启动另一个连接。但是,正在调用 async_write(即 handle_write)的回调函数!

这是我的服务器和客户端代码:

主要.cpp

#include "casperServer.h"
#include <iostream>

int main(int argc, char* argv[])
{
  try
  {
      casperServer s("0.0.0.0", "7000");
      s.run();
  }
  catch (std::exception& e)
  {
    std::cerr << "exception: " << e.what() << "\n";
  }

  return 0;
}

服务器.cpp

#include "casperServer.h"
#include <boost/bind.hpp>


casperServer::casperServer(const std::string& address, const std::string& port)
    :_acceptor(_ioService),
     _connection()
{

    boost::asio::ip::tcp::resolver resolver(_ioService);
    boost::asio::ip::tcp::resolver::query query(address, port);
    boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);

    _acceptor.open(endpoint.protocol());
    _acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
    _acceptor.bind(endpoint);
    _acceptor.listen();


    //Starting the acceptor
    //start_accept();
}

void casperServer::run()
{
    std::cout<< "Running ioService" <<std::endl;
    start_accept();
    _ioService.run();

}

void casperServer::start_accept()
{
    std::cout<< "Creating connection instance ..." <<std::endl;
    _connection.reset(new casperConnection(_ioService));

    std::cout<< "Accept connection" <<std::endl;
    _acceptor.async_accept( _connection->socket(),
                            boost::bind(    &casperServer::handle_accept, this,
                                            boost::asio::placeholders::error));


}

void casperServer::handle_accept(const boost::system::error_code& e)
{

    std::cout<< "Connection accepted ..." <<std::endl;

    if (!e)
    {
        _connection->start();
    }

    std::cout<< "Restarting connection accept ..." <<std::endl;
    start_accept();
}  

连接.cpp

#include <iostream>
#include "casperConnection.h"
#include <boost/bind.hpp>

casperConnection::casperConnection(boost::asio::io_service& io_service)
    :_socket(io_service)
{

}


boost::asio::ip::tcp::socket& casperConnection::socket()
{
    return _socket;
}

void casperConnection::start()
{
      std::cout<< "Writing to client ->" <<std::endl;
      std::cout << "...sigaling READY"<< std::endl;
      boost::asio::async_write( _socket, boost::asio::buffer("Server READY ..."),
                                boost::bind(    &casperConnection::handle_write, shared_from_this(),
                                                boost::asio::placeholders::error));
}

void casperConnection::handle_read(const boost::system::error_code& e, std::size_t bytes_transferred)
{
    std::cout<<"[Handle_read]!"<<std::endl;

    _inputBuffer.clear();

    std::copy(_readBuffer.begin(), _readBuffer.begin()+bytes_transferred, std::back_inserter(_inputBuffer));

    std::cout << "Byte recieved: "<<bytes_transferred<< std::endl;
    std::cout << "Data: "<<_inputBuffer<< std::endl;

    _inputBuffer= _inputBuffer + " ...OK";

    boost::asio::async_write(   _socket, boost::asio::buffer(_inputBuffer, _inputBuffer.length()),
                                boost::bind(    &casperConnection::handle_write, shared_from_this(),
                                                boost::asio::placeholders::error));
}


void casperConnection::handle_write(const boost::system::error_code& e)
{
    std::cout<<"[Handle_write]!"<<std::endl;

    _socket.async_read_some(    boost::asio::buffer(_readBuffer),
                                boost::bind(    &casperConnection::handle_read, shared_from_this(),
                                                boost::asio::placeholders::error,
                                                boost::asio::placeholders::bytes_transferred));

    if(_readBuffer.empty())
    {
        std::cout<<"Buffer empty!"<<std::endl;
    }
}

这是我的客户端代码:

主要.cpp

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

#include "Client.h"

using boost::asio::ip::tcp;

int main(int argc, char* argv[])
{
    Client _client("127.0.0.1", "7000");

    _client.Connect();

    return 0;
}

客户端.cpp

#include <iostream>

Client::Client(const std::string& address, const std::string& port)
{
    std::cout<<"Client CTOR "<<std::endl;

    boost::asio::ip::tcp::resolver resolver(_ioService);
    boost::asio::ip::tcp::resolver::query query(address, port);
    boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);

    initConnection(endpoint);
}

Client::~Client()
{

}

void Client::initConnection(boost::asio::ip::tcp::endpoint ep)
{
    std::cout<<"Initializing connection "<<std::endl;

    _connection.reset(new clientConnection(_ioService));
    _connection->socket().async_connect(ep, boost::bind(&Client::on_connect, this, boost::asio::placeholders::error));

}


void Client::Connect()
{
    std::cout<<"Calling ioService run."<<std::endl;
    _ioService.run();
}


void Client::on_connect(const boost::system::error_code& e)
{
    std::cout << "On connection accept ..." << std::endl;

    if (!e)
    {
        _connection->start();
    }
}

连接.cpp

#include  "clientConnection.h"
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <iostream>


clientConnection::clientConnection(boost::asio::io_service& io_service)
    :_socket(io_service)
{
    std::cout<<"Client Connection CTOR"<<std::endl;
}

clientConnection::~clientConnection()
{

}

boost::asio::ip::tcp::socket& clientConnection::socket()
{
    return _socket;
}

void clientConnection::start()
{

     _socket.async_read_some(   boost::asio::buffer(_buffer),
                                boost::bind(&clientConnection::on_read, shared_from_this(),
                                boost::asio::placeholders::error,
                                boost::asio::placeholders::bytes_transferred));


}


void clientConnection::on_read(const boost::system::error_code& e, std::size_t bytes_transferred)
{

    std::cout<<"Server msg: "<<_buffer.c_array()<<std::endl;
    std::cout<<bytes_transferred<< " bytes read."<<std::endl;

    _buffer.assign(0);

    std::cout<<">>";
    std::getline(std::cin, input);
    std::cout<<"Sending to server: "<<input<<std::endl;


    boost::asio::async_write(   _socket, boost::asio::buffer(input, input.length()),
                                boost::bind(    &clientConnection::on_write, shared_from_this(),
                                                boost::asio::placeholders::error));

}

void clientConnection::on_write(const boost::system::error_code& e)
{

         _socket.async_read_some(   boost::asio::buffer(_buffer),
                                    boost::bind(&clientConnection::on_read, shared_from_this(),
                                    boost::asio::placeholders::error,
                                    boost::asio::placeholders::bytes_transferred));
}

这是我在控制台中的输出:

Running ioService
Creating connection instance ...
Accept connection
Connection accepted ...
Writing to client ->
...sigaling READY
Restarting connection accept ...
Creating connection instance ...
Accept connection
[Handle_write]!

你可以看到,在写完 READY 命令后,服务器正在初始化另一个连接,我不确定为什么。

有什么建议吗?

最佳答案

据我所知,接受另一个连接没有问题。这只是您添加打印件的方式。

void casperServer::start_accept()
{
    std::cout<< "Creating connection instance ..." <<std::endl;
    _connection.reset(new casperConnection(_ioService));

    std::cout<< "Accept connection" <<std::endl;
    _acceptor.async_accept( _connection->socket(),
                            boost::bind(    &casperServer::handle_accept, this,
                                            boost::asio::placeholders::error));


}

void casperServer::handle_accept(const boost::system::error_code& e)
{

    std::cout<< "Connection accepted ..." <<std::endl;

    if (!e)
    {
        _connection->start();
    }

    std::cout<< "Restarting connection accept ..." <<std::endl;
    start_accept();
}  

根据上面的代码,在接受第一个连接后,将调用handle_accept,您可以在其中启动连接实例,然后再次调用start_accept。在 start_accept 中打印“Creating connection ....”和“Accept connection....”,然后将 accept 任务分派(dispatch)给 io_service.

来自您的日志:

Running ioService
Creating connection instance ...
Accept connection
Connection accepted ...  // This shows when connection was actually accepted
Writing to client ->
...sigaling READY
Restarting connection accept ...
Creating connection instance ...
Accept connection // This is a print just before dispatching the accept task to io_service, so not actually accepting a connection
[Handle_write]!

关于c++ - boost 异步服务器两次接受连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39030638/

相关文章:

c++ - VS : Include ressource files in build/exe

c++ - 错误:没有匹配函数来调用‘PSTUNClient::PSTUNClient

c++ - 邮寄消息 : How to post a message to a process that does not have a window?

c++ - C++中varchar(string)的哈希函数

java - 如何使用异步套接字?

javascript - 需要在查看模式和编辑模式下获取具有不同值的 EditText Cell

c++ - Boost序列化编译报错,一头雾水

c++ - 我可以为 Boost.Spirit.Qi 中的内存分配给列表运算符 (%) 提示吗?

c# - 异步任务c#

c++ - 多线程:apache 可移植运行时与 boost::thread?