22 Şubat 2018 Perşembe

asio udp socket Sınıfı

Giriş
Şu satırı dahil ederiz.
#include <boost/asio.hpp>
Eğer future kullanacaksak şu satırı dahil ederiz.
#include <boost/asio/use_future.hpp>
Şu satırı dahil ederiz.
namespace udp = boost::asio::ip::udp;
Sunucular için şöyle yaparız.
1. Constructor  - endpoint
2. async_receive_from

Sunucular için şöyle yaparız.
1. Constructor - default
2. open
3. set_option
4. bind
4. async_receive_from
Şöyle yaparız.
boost::asio::io_service ios;
udp::socket socket{ios};
boost::array<char, 1024> recv_buffer;
udp::endpoint ep;

socket.open(udp::v4());
socket.bind(udp::endpoint(address::from_string("127.0.0.1"),13251);
Daha sonra şöyle yaparız.
boost::array<char, 1024> recv_buffer;
udp::endpoint ep;

void handle_receive(const boost::system::error_code& ec, size_t bytes) {
...
}

socket.async_receive_from(boost::asio::buffer(recv_buffer),
            ep,
            boost::bind(&handle_receive, ...));
İstemciler için şöyle yaparız.
1. Constructor
2. open ()
3. send_to
Şöyle yaparız.
std::string str = ...;
boost::asio::io_service ios;
udp::socket socket(ios);
udp::endpoint ep = udp::endpoint(address::from_string("127.0.0.1"),13251);
socket.open(udp::v4());

boost::system::error_code err;
auto sent = socket.send_to(boost::asio::buffer(str), ep, 0, err);
socket.close();

Constructor - io_service
Şöyle yaparız.
boost::asio::io_service ios;
udp::socket socket (ios);
Constructor - io_service + udp::endpoint
Sunucu socketlerde kullanılır.
Örnek
Şöyle yaparız.
udp::endpoint ep (udp::v6(), 13);

asio::io_service ios;
socket socket (ios, ep);
Örnek
Şöyle yaparız.
io_service io_service;
int port_number = ...;
socket (io_service, endpoint(udp::v4(), port_number))
async_connect metodu
Örnek
Şöyle yaparız. Bu işlemin her zaman başarılı olması gerekir.
//create endpoint
boost::asio::ip::udp::endpoint ep (
  boost::asio::ip::address::from_string("10.0.0.4"), 
  1337
);

//connect socket
socket.async_connect(ep, connect_callback);
vıid connect_callback (const boost::system::error_code& ec)
{
  //check for errors
  if (ec) 
  {
    ...
  }
  else
  {
    ...
  }   
  
}
async_receive metodu
null_buffers
Şöyle yaparız.
socket.async_receive(boost::asio::null_buffers(), handler);
handler içinde şöyle yaparız.
// in the handler code
unsigned int available = socket.available();
buffer = resize_buffer_if_needed(available);
unsigned int packetSize = socket.receive_from(
  boost::asio::buffer(buffer, available), ep, 0, ec);
async_receive_from
Bu metodun 4 tane overload edilmiş hali var.
1.buffer + handler
2. buffer + flags + handler
3. buffer + endpoint + handler
4. buffer + endpoint + flags + handler.

async_receive_from metodu - future
Bu metod 1.60 sürümü ile geliyor.
Örnek
Şöyle yaparız.
std::future<std::size_t> future = socket.async_receive_from(
  boost::asio::buffer(recv_buf),
  ep,
  boost::asio::use_future);
Örnek
Şöyle yaparız. future.get() çağrısı ile verinin okunması beklenebilir.
std::array<char, 128> buf;
udp::endpoint ep;
std::future<std::size_t> future =
  socket.async_receive_from(
    boost::asio::buffer(buf),
    ep,
    boost::asio::use_future);

// Do other things here while the receive completes.

std::cout.write(
  buf.data(),
  future.get()); // Blocks until receive is complete.
Flag ile kullanmak istersek şöyle yaparız.
std::future<std::size_t> future = socket.async_receive_from (
  boost::asio::buffer(recv_buf), 
  ep, 
  0, 
  boost::asio::use_future);
async_receive_from metodu - buffer + endpoing + handler
boost::array
Örnek
Şöyle yaparız.
boost::array<char, 100> buf;
udp::endpoint ep;

socket.async_receive_from(
            asio::buffer(buf),
            ep,
            handler
        );
Örnek
Elimizde bir buffer olduğunu varsayalım.
boost::array<char, 100> recv_buffer;
Eğer C++11 kullanıyorsak boost::array yerine std::array de kullanılabilir.
std::array<char,100> recv_buffer;
Verinin nereden geldiğini bilmek istediğimizi varsayalım.
endpoint remote_endpoint;
Şöyle yaparız.
socket.async_receive_from(
            boost::asio::buffer(recv_buffer), remote_endpoint,
            boost::bind(&myclass::handle_receive, this,
                        boost::asio::placeholders::error,
                        boost::asio::placeholders::bytes_transferred));
Metodumuz şöyle olmalı. Genelde !error koşuluna bakmak yeterli.
void handle_receive(const boost::system::error_code& error,
                        std::size_t bytes_transferred)
{
  if (!error || error == boost::asio::error::message_size)
  {...}
}
Eğer hata yoksa veriyi string'e şöyle çeviririz.
std::string(recv_buffer.data(), recv_buffer.data() + bytes_transferred)
std::array
Şöyle yaparız.
std::array<char, 128> buf;
udp::endpoint ep;

socket.async_receive_from(
      boost::asio::buffer(buf),
      ep,
      handler);
Handler şöyledir.
void handle_receive (const system::error_code error, size_t) {
  if (!error || error == asio::error::message_size) {
    ...
   }
}
async_receive_from metodu - buffer + endpoing + flags + handler
Metodun imzası şöyle.
template <typename MutableBufferSequence,typename Handler>
void async_receive_from(const MutableBufferSequence buffers&, 
                        endpoint_type& sender_endpoint,
                        socket_base::message_flags flags, 
                        Handler& handler)

async_send_to metodu - future
Şöyle yaparız.
std::future<std::size_t> send_length =
  socket.async_send_to(..., boost::asio::use_future);

// Do other things here while the send completes.

send_length.get(); // Blocks until the send is complete. Throws any errors.
async_send_to metodu - handler
Şöyle yaparız.
boost::shared_ptr<string> message(new string("..."));
udp::endpoint ep = ...;

socket.async_send_to(
                asio::buffer(*message),
                ep,
                handler
            );
Gönderilen mesajı yakalamak istersek handler şöyledir.
void handle_send (boost::shared_ptr<string> msg, 
  const system::error_code &code, size_t)
{... }
async_send_to - scatter gather
Birden fazla bellek alanını aynı anda göndermek için kullanılır. Sanırım veri tek bir UDP ile gönderiliyor. Şöyle yaparız.
typedef std::deque<boost::asio::const_buffer> ConstBuffers;

std::string msg_1("Blah");
...
std::string msg_n("Blah");

ConstBuffers buffers;
buffers.push_back(msg_1);
...
buffers.push_back(msg_n);

socket_.async_send_to(buffers, tx_endpoint_, write_handler);
available
Okumak için kaç byte olduğunu belirtir.  Available 50 byte dönerse bile okunacak ilk paket 13 byte olabilir.
unsigned int available = socket.available();
bind metodu
Şöyle yaparız.
udp::endpoint ep = ...;
socket.bind (ep);
Şöyle yaparız.
udp::endpoint ep(ip::address::from_string("0.0.0.0"), 5353);
socket.bind (ep);
close metodu
Şöyle yaparız.
boost::system::error_code ec;
socket.close (ec);
io_control metodu
Okumaya hazır kaç byte olduğunu öğrenmek için şöyle yaparız.
boost::asio::socket_base::bytes_readable command(true);
socket.io_control(command);
std::size_t bytes_readable = command.get();
open metodu - protocol
Şöyle yaparız.
udp::endpoint ep = ...;
socket.open  (ep.protocol());
Şöyle yaparız.
socket.open(boost::asio::ip::udp::v4());
Şöyle yaparız.
socket.open (udp::v6());
receive_from metodu - buffer + endpoint
boost::array
Örnek
Şöyle yaparız.
boost::array<char, 128> buf;
udp::endpoint ep;
size_t len = socket.receive_from (boost::asio::buffer(buf), ep);
Örnek
Verinin nereden geldiğini bilmek istediğimizi varsayalım.
endpoint sender_endpoint;
Şöyle yaparız.
boost::array<unsigned char, 8192> temp; 
size_t len = socket.receive_from(
                         boost::asio::buffer(temp), sender_endpoint);
std::vector
Şöyle yaparız.
udp::endpoint ep;
std::vector<unsigned char> v;
v.resize(1024);
std::size_t len = socket.receive_from(boost::asio::buffer(v), ep);
receive_from metodu - buffer + endpoint + error_code
Eğer istersek hata kodu ile beraber kullanabiliriz. available() metodu ile okunabilecek byte sayısını öğrendiğimizi varsayalım.
boost::system::error_code ec;
unsigned int len = socket.receive_from(
        boost::asio::buffer(temp, available), sender_endpoint, 0, ec);
Hata kodunu kontrol etmek gerekir.
if(ec) 
{
  ...
}
send_to metodu  - buffer + endpoint
boost::array
Örnek
Şöyle yaparız.
udp::endpoint ep = ...;

boost::array<char, 1> buf = ...;
socket.send_to (boost::asio::buffer(buf), ep);
Örnek
Elimizde bir endpoint ve veri olduğunu varsayalım.
boost::array<char, 100> send_buf  = {{ 0 }};
boost::asio::ip::udp::endpoint endpoint;
Şöyle yaparız.
socket.send_to(boost::asio::buffer(send_buf), endpoint);
char*
Şöyle yaparız.
udp::endpoint ep = ...;
socket.send_to(boost::asio::buffer("abc", 3), ep);
set_option metodu
reuse seçeneği
Şöyle yaparız.
socket.set_option (udp::socket::reuse_address (true));
broadcast seçeneği
Şöyle yaparız.
socket.set_option(boost::asio::socket_base::broadcast(true));
multicast seçeneği - address
Açıklaması şöyle. Alan taraf bind ile adrese bağlanmalıdır.

Adres olarak şu kullanılabilir.
239.255.255.251:5353
Şu kullanılabilir.
231.11.1.5:6005
Gerekirse reuse_address ile başka uygulamaların da multicast paketleri almasına izin verir.
[...] We want the receiving socket to bind the multicast group and port, say 239.255.1.2 port 8888. (Recall that we could just bind the wildcard IP address and port 8888, but binding the multicast address prevents the socket from receiving any other datagrams that might arrive destined for port 8888.) We then want the receiving socket to join the multicast group. The sending socket will send datagrams to this same multicast address and port, say 239.255.1.2 port 8888.
Şöyle yaparız.
boost::asio::ip::address multicast_address = ...;
socket.set_option (boost::asio::ip::multicast::join_group (multicast_address));
Şöyle yaparız.
socket.set_option(boost::asio::ip::multicast::join_group(
  ip::address::from_string(MULTICAST_ADDRESS)));
Şöyle yaparız.
ip::address multicast_address = ...;
sock.set_option(ip::multicast::join_group(multicast_address.to_v4()));
Şöyle yaparız.
socket.set_option(
  boost::asio::ip::multicast::enable_loopback(false));
Multicast belli bir arayüzden gitsin istersek şöyle yaparız.
boost::asio::ip::address addr = ...;
socket.set_option(boost::asio::ip::multicast::outbound_interface(addr.to_v4()));
timestamp seçeneği
Şöyle bir seçeneğin eklenmesi düşünülmüş ama gerçekleşmemiş.
sock.set_option(ip::unicast::timestamp(true));

Hiç yorum yok:

Yorum Gönder