Giriş
Şu satırı dahil ederiz.
open + bind çağrıları yapılabilir.
Şöyle yaparız.
Şöyle yaparız.
iostream nesnesi içinde tcp::socket barındırır. Şöyle yaparız.
Acceptor'a boost::asio::ip::tcp tipinde bir socket verilir.
Elimizde bir tcp::iostream sınıfı olsun.
Şu satırı dahil ederiz.
#include <boost/asio.hpp>
Kolay kullanım için şu satırı dahil ederiz.using boost::asio::ip::tcp;
Kalıtım şöyledir.acceptor -> basic_socket_acceptor -> socket_base
Constructor - enpoint
Eğer bind işlemini gerçekleşmez ise exception fırlatır. Bu çağrı yerineopen + bind çağrıları yapılabilir.
Şöyle yaparız.
tcp::endpoint ep (tcp::v4(), 1234);
tcp::acceptor acceptor(ios, ep);
Şöyle yaparız.tcp::acceptor acceptor(ios,tcp::enpoint(tcp::v4(),
134);
Bu sınıfı şöyle sarmalarız.
listener::listener (io_service& io_service, std::string ip, short port)
:acceptor(io_service, tcp::endpoint(ip::address_v4::from_string(ip), port)),
socket(io_service)
{
logger << ("Network bound" << acceptor.local_endpoint().address().to_string()
<< acceptor.local_endpoint().port();
start_accepting();
}
İçinde bir tane socket barındırır.class listener
{
private:
boost::asio::ip::tcp::acceptor acceptor;
boost::asio::ip::tcp::socket socket;
};
accept metodu - tcp::socketŞöyle yaparız.
tcp::socket sock = ...;
acceptor.accept (sock);
accept çağrısından sonra sock nesnesini yaşaması gerekir. Eğer sock nesnesi bir scope içinde yaratılırsa ve scope'tan çıkarken otomatik olarak yok edilirse yanlış olur.tcp::socket sock (...);
acceptor.accept (sock);
...
~socket();
accept metodu - tcp::iostreamiostream nesnesi içinde tcp::socket barındırır. Şöyle yaparız.
tcp::iostream ss;
boost::system::error_code ec;
acceptor.accept (*ss.rdbuf(), ec);
async_accept metodu - tcp::socket
Bu çağrıdan önce acceptor nesnesinin bind() ve listen () metodları çağrılmış olmalıdır.Acceptor'a boost::asio::ip::tcp tipinde bir socket verilir.
acceptor.async_accept(sock,
boost::bind(&accept_handler, asio::placeholders::error));
İstersek lambda kullanabiliriz. Şöyle yaparız.acceptor.async_accept(socket, [this](const system::error_code& e){
...
})
async_accept metodu - tcp::iostream
iostream nesnesi içinde tcp::socket barındırır. Bu çağrıdan önce acceptor nesnesinin bind() ve listen () metodları çağrılmış olmalıdır.Elimizde bir tcp::iostream sınıfı olsun.
tcp::iostream ss;
Şöyle yaparız.acceptor.async_accept(*ss.rdbuf(),
boost::bind(&Server::handleAccept, this,
boost::asio::placeholders::error, boost::ref( acceptor ) ) );
bind metodu - endpoint
Şöyle yaparız.
Şöyle yaparız.
Şöyle yaparız.
tcp::endpoint ep (ip::tcp::v4(), 1500);
acceptor.bind(ep);
close metoduŞöyle yaparız.
acceptor.close();
get_io_service metoduŞöyle yaparız.
acceptor.get_io_service();
is_open metodu
Şöyle yaparız.
if(acceptor.is_open ()) {...}
listen metodu
Şöyle yaparız.
Şöyle yaparız.
Şöyle yaparız.
Handler Nasıl Yazılır
Şöyle yaparız.
acceptor.listen ();
open metodu - protocolŞöyle yaparız.
tcp::endpoint ep (tcp::v4(), 1500);
acceptor.open (ep.protocol());
set_option metoduŞöyle yaparız.
acceptor.set_option (tcp::acceptor::reuse_address(true));
Şöyle yaparızacceptor.set_option(boost::asio::socket_base::reuse_address(true));
DiğerHandler Nasıl Yazılır
Hem iostream hem de socket kullanan handler aynıdır. Parametreleri error ve isteğe bağlı olarak acceptor'ın kendisi olabilir. Hata kodunu kontrol etmek gerekir.
void handleAccept(const error_code& error, acceptor& acceptor)
{
if(error)
std::cout << error.message() << "(" << error.value() << ")" << std::endl;
}
1. acceptor içindeki socket ile yeni bir tcp_client nesnesi oluşturulur.void start_accepting (){
acceptor.async_accept(socket, [this](boost::system::error_code ec)
{
if (!ec)
{
logger <<"Connection" << socket.remote_endpoint().address().to_string());
std::make_shared<tcp_client>(socket)->start_receiving();
}
else
{
acceptor.close();
}
start_accepting();
});
}
2. tcp_client nesnesi std::enabled_shared_from_this'ten kalıtan bir sınıftır. Şöyle yaparız.class tcp_client : public std::enable_shared_from_this<tcp_client>
{
public:
tcp_client(tcp::socket socket) : socket_(std::move(socket)) {
...
}
void start_receiving() {...}
private:
tcp::socket socket_;
};
Sarmalanan sınıf kendi içinde socket.asyncXXX (buffer, bind (...,std::shared_from_this,...)); çağrıları yapmaya devam ettikçe heap'te yaşamaya devam eder.
3. Benzer şekilde şöyle yaparız. Tek fark socket nesnesi acceptor içinde değil, client nesnesi içine yaşar.
Şöyle yaparız.
3. Benzer şekilde şöyle yaparız. Tek fark socket nesnesi acceptor içinde değil, client nesnesi içine yaşar.
std::shared_ptr<Connection> createConnection(){
std::shared_ptr<Connection> newConnection = Connection::create(m_ioService);
m_acceptor.accept(newConnection->getSocket());
return newConnection;
}
4. Benzer şekilde şöyle yaparız. Socket nesnesi acceptor içinde dğil client nesnesi içinde yaşar. acceptor connection nesnesine run() çağrısı yapar ve kendini tekrar başlatır.void begin_accepting(asio::ip::tcp::acceptor& acceptor)
{
auto candidate = std::make_shared<connection>(acceptor.get_io_service());
acceptor.async_accept(candidate->socket_, [candidate, &acceptor](auto const& ec)
{
if (not ec) {
candidate->run();
begin_accepting(acceptor);
}
});
}
ÖrnekŞöyle yaparız.
class Server
{
public:
Server(boost::asio::io_service& p_service, unsigned p_port) :
m_service(p_service),
m_acc(m_service, boost::asio::ip::tcp::endpoint( asio::ip::tcp::v4(), p_port ) ),
m_session( std::make_shared< Session >() )
{
StartListen();
}
private:
void StartListen()
{
m_acc.async_accept(
m_session->tcp_stream().rdbuf(),
std::bind(&Server::AcceptHandler, this, _1) );
}
void AcceptHandler(const boost::system::error_code& p_error)
{
if( !p_error )
{
auto ses = std::make_shared< Session >();
std::swap( ses, m_session );
ses->InitLifeCircle(); // Start whatever logic you needed.
StartListen();
}
}
private:
boost::asio::io_service& m_service;
boost::asio::ip::tcp::acceptor m_acc;
std::shared_ptr< Session > m_session;
};
Hiç yorum yok:
Yorum Gönder