Boost异步服务器接受两次连接

Boost asynchronous server accepting connection twice

本文关键字:两次 连接 异步 服务器 Boost      更新时间:2023-10-16

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

现在我所经历的是在服务器接受连接并发送第一个"READY"消息后,它接受另一个连接并实例化新的连接类。但之后一切都如预期的那样。

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

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

main.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;
}

server.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();
}  

Connection.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;
    }
}

下面是我的客户端代码:

main.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;
}

Client.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();
    }
}

Connection.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。在io_service中打印"创建连接...."answers"接受连接....",然后将accept任务分配给CC_5。

从你的日志:

<>以前ioService运行创建连接实例…接受连接接受连接…//显示连接实际接受的时间给客户写信->…sigaling准备好了重新启动连接接受…创建连接实例…Accept connection//这是在将Accept任务分派给io_service之前打印的,所以实际上并没有接受连接(Handle_write) !