Stories

Detail Return Return

C++ Boost.Asio異步編程 - Stories Detail

Boost.Asio是Boost庫中非常著名的I/O組件,是用於網絡和低層IO編程的跨平台C++庫,為開發者提供了C++環境下穩定的異步模型。本文將介紹Boost庫中Asio的結構及相關異步編程。

Asio三大組件

io_object

I/O對象的集合,其中包含大家所熟悉的socket、deadline_timer等對象,主要功能是提供接口給用户使用。

services服務

邏輯功能的實現者,其中包含提供定時功能的deadline_timer_service、提供socket相關功能的win_iocp_socket_service(windows平台)/reactive_socket_service(其他平台)、作為io_service功能的真正實現者win_iocp_io_service(windows平台)/task_io_service(其他平台)等等服務。

Asio核心組件

在這一層中可以理解為就是io_service,它通過關聯的類service_registry將實現具體功能所需的服務組合起來,再由io_object提供接口給用户使用。

編程實例

TCP異步連接

#include <iostream>
#include <boost/asio.hpp>

// 異步連接回調函數
void on_connect(boost::system::error_code ec)
{
     if (ec)  // 連接失敗, 輸出錯誤碼
         std::cout << "async connect error:" << ec.message() << std::endl;
     else  // 連接成功
         std::cout << "async connect ok!" << std::endl;
 }
 
int main() {
     boost::asio::io_service ios;  // 創建io_service對象
     boost::asio::ip::tcp::endpoint addr(
     boost::asio::ip::address::from_string("127.0.0.1"), 12345);  // server端地址
     boost::asio::ip::tcp::socket conn_socket(ios);  // 創建tcp協議的socket對象
     conn_socket.async_connect(addr, &on_connect);  // 發起異步連接請求
     ios.run();  // 調用io_service::run, 等待異步操作結果
 
     std::cin.get();
     return 0;
}

TCP異步接受連接

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>

// 異步連接回調函數
void on_accept(boost::system::error_code ec, boost::asio::ip::tcp::socket * socket_ptr)
{
     if (ec)  // 連接失敗, 輸出錯誤碼
         std::cout << "async accept error:" << ec.message() << std::endl;
     else  // 連接成功
         std::cout << "async accept from (" << socket_ptr->remote_endpoint() << ")" << std::endl;
 
     // 斷開連接, 釋放資源.
     socket_ptr->close(), delete socket_ptr;
}
 
int main() {
     boost::asio::io_service ios;  // 創建io_service對象
     boost::asio::ip::tcp::endpoint addr(
     boost::asio::ip::address::from_string("0.0.0.0"), 12345);  // server端地址
     boost::asio::ip::tcp::acceptor acceptor(ios, addr, false);  // 創建acceptor對象
     boost::asio::ip::tcp::socket * socket_ptr = new boost::asio::ip::tcp::socket(ios);
     acceptor.async_accept(*socket_ptr
         , boost::bind(&on_accept, boost::asio::placeholders::error, socket_ptr));  // 調用異步accept請求
     ios.run();  // 調用io_service::run, 等待異步操作結果
 
     std::cin.get();
     return 0;
}

TCP異步讀寫數據

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/array.hpp>
 
typedef boost::shared_ptr<boost::asio::ip::tcp::socket> socket_ptr_t;
typedef boost::array<char, 128> buffer_t;
typedef boost::shared_ptr<buffer_t> buffer_ptr_t;
 
// 異步讀數據回調函數
void on_read(boost::system::error_code ec
     , std::size_t len, socket_ptr_t socket_ptr, buffer_ptr_t buffer_ptr)
{
     if (ec)
         std::cout << "async write error:" << ec.message() << std::endl;
     else
     {
         std::cout << "async read size:" << len;
         std::cout << " info:" << std::string((char*)buffer_ptr->begin(), len) << std::endl;
 
         // auto release socket and buffer.
     }
}
 
// 異步寫數據回調函數
void on_write(boost::system::error_code ec
     , std::size_t len, socket_ptr_t socket_ptr, buffer_ptr_t buffer_ptr)
{
     if (ec)
         std::cout << "async write error:" << ec.message() << std::endl;
     else
     {
         std::cout << "async write size:" << len << std::endl;
         socket_ptr->async_read_some(boost::asio::buffer(buffer_ptr.get(), buffer_t::size())
             , boost::bind(&on_read, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred
                 , socket_ptr, buffer_ptr));
     }
}
 
// 異步連接回調函數
void on_accept(boost::system::error_code ec, socket_ptr_t socket_ptr)
{
     if (ec)  // 連接失敗, 輸出錯誤碼
     {
         std::cout << "async accept error:" << ec.message() << std::endl;
     }
     else  // 連接成功
     {
         std::cout << "async accept from (" << socket_ptr->remote_endpoint() << ")" << std::endl;
         buffer_ptr_t buffer_ptr(new buffer_t);
         strcpy_s((char*)buffer_ptr->begin(), buffer_t::size(), "abcdefg");
         socket_ptr->async_write_some(boost::asio::buffer(buffer_ptr.get(), strlen((char*)buffer_ptr->begin()))
             , boost::bind(&on_write, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred
                 , socket_ptr, buffer_ptr));
     }
}
 
int main() {
     boost::asio::io_service ios;  // 創建io_service對象
     boost::asio::ip::tcp::endpoint addr(
         boost::asio::ip::address::from_string("0.0.0.0"), 12345);  // server端地址
     boost::asio::ip::tcp::acceptor acceptor(ios, addr, false);  // 創建acceptor對象
     socket_ptr_t socket_ptr(new boost::asio::ip::tcp::socket(ios));
     acceptor.async_accept(*socket_ptr
         , boost::bind(&on_accept, boost::asio::placeholders::error, socket_ptr));  // 調用異步accept請求
     ios.run();  // 調用io_service::run, 等待異步操作結果
 
     std::cout << "press enter key...";
     std::cin.get();
     return 0;
}  

TCP強制關閉連接

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/array.hpp>

typedef boost::shared_ptr<boost::asio::ip::tcp::socket> socket_ptr_t;
typedef boost::array<char, 128> buffer_t;
typedef boost::shared_ptr<buffer_t> buffer_ptr_t;
 
// 異步讀數據回調函數
void on_read(boost::system::error_code ec
     , std::size_t len, socket_ptr_t socket_ptr, buffer_ptr_t buffer_ptr)
{
     if (ec)  // 連接失敗, 輸出錯誤碼
     {
         std::cout << "async read error:" << ec.message() << std::endl;
     }
}
 
// 異步寫數據回調函數
void on_write(boost::system::error_code ec
     , std::size_t len, socket_ptr_t socket_ptr, buffer_ptr_t buffer_ptr)
{
     if (ec)  // 連接失敗, 輸出錯誤碼
     {
         std::cout << "async write error:" << ec.message() << std::endl;
     }
}
 
// 異步連接回調函數
void on_accept(boost::system::error_code ec, socket_ptr_t socket_ptr)
{
     if (ec)  // 連接失敗, 輸出錯誤碼
     {
         std::cout << "async accept error:" << ec.message() << std::endl;
     }
     else  // 連接成功
     {
         std::cout << "async accept from (" << socket_ptr->remote_endpoint() << ")" << std::endl;
 
         {
             buffer_ptr_t buffer_ptr(new buffer_t);
             strcpy_s((char*)buffer_ptr->begin(), buffer_t::size(), "abcdefg");
             socket_ptr->async_write_some(boost::asio::buffer(buffer_ptr.get(), strlen((char*)buffer_ptr->begin()))
                 , boost::bind(&on_write, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred
                 , socket_ptr, buffer_ptr));
         } 
         {
             buffer_ptr_t buffer_ptr(new buffer_t);
             socket_ptr->async_read_some(boost::asio::buffer(buffer_ptr.get(), buffer_t::size())
                 , boost::bind(&on_read, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred
                 , socket_ptr, buffer_ptr));
         }
 
         /// 強制關閉連接
         socket_ptr->close(ec);
         if (ec)
             std::cout << "close error:" << ec.message() << std::endl;
     }
}
 
int main()
{
     boost::asio::io_service ios;  // 創建io_service對象
     boost::asio::ip::tcp::endpoint addr(
         boost::asio::ip::address::from_string("0.0.0.0"), 12345);  // server端地址
     boost::asio::ip::tcp::acceptor acceptor(ios, addr, false);  // 創建acceptor對象
     socket_ptr_t socket_ptr(new boost::asio::ip::tcp::socket(ios));
     acceptor.async_accept(*socket_ptr
         , boost::bind(&on_accept, boost::asio::placeholders::error, socket_ptr));  // 調用異步accept請求
     socket_ptr.reset();
     ios.run();  // 調用io_service::run, 等待異步操作結果
 
     std::cout << "press enter key...";
     std::cin.get();
     return 0;
} 

TCP優雅地關閉連接

#include <iostream>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/array.hpp>
 
typedef boost::shared_ptr<boost::asio::ip::tcp::socket> socket_ptr_t;
typedef boost::array<char, 32> buffer_t;
typedef boost::shared_ptr<buffer_t> buffer_ptr_t;
  
// 異步讀數據回調函數
 void on_read(boost::system::error_code ec
     , std::size_t len, socket_ptr_t socket_ptr, buffer_ptr_t buffer_ptr)
 {
     static int si = 0;
     if (ec)  // 連接失敗, 輸出錯誤碼
     {
         std::cout << "async read(" << si++ << ") error:" << ec.message() << std::endl;
         socket_ptr->shutdown(boost::asio::socket_base::shutdown_receive, ec);
         socket_ptr->close(ec);
         if (ec)
             std::cout << "close error:" << ec.message() << std::endl;
     }
     else
     {
         std::cout << "read(" << si++ << ") len:" << len << std::endl;
 
         socket_ptr->async_read_some(boost::asio::buffer(buffer_ptr.get(), buffer_t::size())
             , boost::bind(&on_read, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred
             , socket_ptr, buffer_ptr));
     }
 }
 
 // 異步寫數據回調函數
 void on_write(boost::system::error_code ec
     , std::size_t len, socket_ptr_t socket_ptr, buffer_ptr_t buffer_ptr)
 {
     if (ec)  // 連接失敗, 輸出錯誤碼
     {
         std::cout << "async write error:" << ec.message() << std::endl;
     }
     else
     {
         /// 優雅地關閉連接
         socket_ptr->shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec);
         if (ec)
             std::cout << "shutdown send error:" << ec.message() << std::endl;
     }
 }
 
 // 異步連接回調函數
 void on_accept(boost::system::error_code ec, socket_ptr_t socket_ptr)
 {
     if (ec)  // 連接失敗, 輸出錯誤碼
     {
         std::cout << "async accept error:" << ec.message() << std::endl;
     }
     else  // 連接成功
     {
         std::cout << "async accept from (" << socket_ptr->remote_endpoint() << ")" << std::endl;
 
        {
             buffer_ptr_t buffer_ptr(new buffer_t);
             socket_ptr->async_read_some(boost::asio::buffer(buffer_ptr.get(), buffer_t::size())
                 , boost::bind(&on_read, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred
                 , socket_ptr, buffer_ptr));
         }
 
         {
             buffer_ptr_t buffer_ptr(new buffer_t);
             strcpy_s((char*)buffer_ptr->begin(), buffer_t::size(), "abcdefg");
             socket_ptr->async_write_some(boost::asio::buffer(buffer_ptr.get(), strlen((char*)buffer_ptr->begin()))
                 , boost::bind(&on_write, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred
                 , socket_ptr, buffer_ptr));
         }
     }
}

int main()
{ 
     boost::asio::io_service ios;  // 創建io_service對象
     boost::asio::ip::tcp::endpoint addr(
         boost::asio::ip::address::from_string("0.0.0.0"), 12345);  // server端地址
     boost::asio::ip::tcp::acceptor acceptor(ios, addr, false);  // 創建acceptor對象
     socket_ptr_t socket_ptr(new boost::asio::ip::tcp::socket(ios));
     acceptor.async_accept(*socket_ptr
         , boost::bind(&on_accept, boost::asio::placeholders::error, socket_ptr));  // 調用異步accept請求
     socket_ptr.reset();
     ios.run();  // 調用io_service::run, 等待異步操作結果
 
     std::cout << "press enter key...";
     std::cin.get();
     return 0;
}

Add a new Comments

Some HTML is okay.