2016-08-19 9 views
1

私はboost.asio非同期サーバーで作業しています。 現時点では、サーバーコードは非常にシンプルです。クライアントからの接続を受け入れ、接続を受け入れると、クライアントにREADYメッセージを送信します。クライアントはREADYメッセージを印刷し、ユーザーがクライアントコンソールにメッセージを書き込むことを許可します。クライアントに入力されたメッセージはすべてサーバーに送信されます。サーバーはメッセージのメッセージとバイトサイズを出力し、その後、追加の "... OK"文字列でクライアントに同じメッセージを返します。2回接続を受け付ける非同期サーバーをブースト

私は、サーバーが接続を受け入れ、最初の "READY"メッセージを送信した後、別の接続を受け入れ、新しい接続クラスをインスタンス化しています。しかしその後、すべてが期待どおりに進んでいます。

私はasync_write(READYメッセージを送るために)を呼び出した後、別の接続をre_initiatingしている理由がわかりません。しかし、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コマンドを書いた直後に、サーバーは別の接続を初期化していますが、その理由はわかりません。

提案がありますか?

答えて

1

私が見る限り、別の接続を受け入れるという問題はありません。それはあなたがプリントを追加した唯一の方法です。上記のコードを1として

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の中には、にacceptタスクをディスパッチする前に、 "接続の作成中...."と "接続を受け入れる..."と表示されます。あなたのログから

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]! 
+0

さて、私は今それを理解すると思うが、それは_connection->スタート()、async_writeが呼び出された後、_connection->スタートの内側に、非同期関数の性質のためのようなものです()が返され、2回目にstart_acceptが呼び出されますか?しかし、最初に受け入れられた接続の場合、読み書き機能はループ内で継続されますか? ...アクセプタは2番目の接続に気をつけていますか? – Pixelord

+1

はい、あなたはそれを持っています。 – Arunmu

関連する問題