[Boost] ASIO學習筆記:network basic– UDP Server

posted in: ASIO, boost, C/C++程式設計, Server | 0

UDP  Server跟TCP Server不同,它是屬於connectionless的技術,因此不需要acceptor去跟client建立連線的步驟。我們只需要利用socket去bind特定的port後,就可以接收到資料。

一個Sync socket的流程如下,圖片引用自此

Socket APIs for connectionless UDP

在ASIO中的Server端程式碼:

#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <string>
#include <boost/thread.hpp>
using namespace std;

void main(){
   boost::system::error_code ec;
   boost::shared_ptr<boost::asio::io_service> io_service(new boost::asio::io_service);
   boost::shared_ptr<boost::asio::io_service::strand> strand(new boost::asio::io_service::strand(*io_service));
   // boost::shared_ptr< boost::asio::io_service::work > work(new boost::asio::io_service::work( *io_service ));    

   try{

       boost::shared_ptr<boost::asio::ip::udp::socket> socket(new 
           boost::asio::ip::udp::socket(*io_service, 
           boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v6(), 12345)));

       boost::asio::ip::udp::endpoint remote_endpoint;
       while(true){    
           
           boost::array<char, 1> buf;
           int size = socket->receive_from(boost::asio::buffer(buf), remote_endpoint, 0, ec);
           if(ec){cout << "receive->" << ec.message() << endl;};
           if(size != 0){
               cout << "get access from->" << remote_endpoint.address() << endl;
           }


           std::string s;
           s.append("->Server say hello to you!\n");

           socket->send_to(boost::asio::buffer(s), remote_endpoint, 0, ec);

       
           if(ec){cout << "send to->" << ec.message() << endl;};
       }

   }catch(std::exception e){
       cout << e.what() << endl;
   }


   io_service->stop();


   std::system("pause");


}

其中:boost::asio::buffer是一個function,它能夠將要傳輸的資料變成buffer object用來供socket將其分解成封包來進行資料的傳輸。

由於上面的程式是使用socket->receive_from,是屬於Sync socket的方法,因此這行會block住直到資料全部接收完畢才會往下執行。

同理socket->send_to也是屬於Sync socket的方法。

client端的程式碼:

#include <iostream>
#include <boost/array.hpp>
#include <boost/asio.hpp>
 
using boost::asio::ip::udp;
 
int main(int argc, char* argv[])
{
      try
      {
     
        boost::asio::io_service io_service;
     
        udp::resolver resolver(io_service);
        udp::resolver::query query(udp::v4(), "localhost", "12345");
     
        udp::endpoint receiver_endpoint = *resolver.resolve(query);
        udp::socket socket(io_service);
        socket.open(udp::v4());  //udp是open後丟資料,不需要connect,然後等待接收(是誰送回來的再用sender_endpoint來確認)
     
        boost::array<char, 1> send_buf;
        socket.send_to(boost::asio::buffer(send_buf), receiver_endpoint);
     
        boost::array<char, 100> recv_buf;
        udp::endpoint sender_endpoint;
        size_t len = socket.receive_from(
            boost::asio::buffer(recv_buf), sender_endpoint);
     
        std::cout.write(recv_buf.data(), len);
      }
      catch (std::exception& e)
      {
        std::cerr << e.what() << std::endl;
      }
     
      system("pause");
      return 0;
}

boost::array<char, 100> recv_buf可以換成char recv_buf[100]。

Leave a Reply

Your email address will not be published. Required fields are marked *