私は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コマンドを書いた直後に、サーバーは別の接続を初期化していますが、その理由はわかりません。
提案がありますか?
さて、私は今それを理解すると思うが、それは_connection->スタート()、async_writeが呼び出された後、_connection->スタートの内側に、非同期関数の性質のためのようなものです()が返され、2回目にstart_acceptが呼び出されますか?しかし、最初に受け入れられた接続の場合、読み書き機能はループ内で継続されますか? ...アクセプタは2番目の接続に気をつけていますか? – Pixelord
はい、あなたはそれを持っています。 – Arunmu