色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

電子發燒友App

硬聲App

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示
電子發燒友網>電子資料下載>電子資料>基于asio的網絡通信框架asio2

基于asio的網絡通信框架asio2

2022-06-22 | zip | 20.50 MB | 次下載 | 2積分

資料介紹

授權協議 GPL
開發語言 C/C++
操作系統 跨平臺
軟件類型 開源軟件
所屬分類 程序開發、 高性能網絡開發庫

軟件簡介

?

開源基于asio的網絡通信框架asio2,支持TCP,UDP,HTTP,RPC,SSL,跨平臺,支持可靠UDP,支持TCP自動拆包,TCP數據報模式等?

C++開發網絡通信程序時用asio是個不錯的選擇,但asio本身是一套函數集,自己還要處理諸如“通信線程池管理、連接及生命周期管理、多線程收發數據的同步保護等”。因此這里對asio進行了一層封裝,大大簡化了對asio的使用。代碼使用了C++17相關功能,所以只能用在C++17以上。

其中http和websocket部分用的是boost::beast,因此如果需要用到http或websocket的功能,則必須使用boost庫,如果用不到http則直接使用獨立的asio即可。在config.hpp中通過對ASIO_STANDALONE這個宏定義的開關,即可設置是使用boost::asio還是使用asio standalone.

代碼大量使用了CRTP模板編程實現(沒有使用virtual而用CRTP實現的靜態多態),因此編譯比較耗時,但執行效率相對較好一點。


github地址https://github.com/zhllxt/asio2

碼云地址https://gitee.com/zhllxt/asio2

A open source cross-platform c++ library for network programming based on asio,support for tcp,udp,http,rpc,ssl and so on.

  • 支持TCP,UDP,HTTP,WEBSOCKET,RPC,ICMP,SERIAL_PORT等;
  • 支持可靠UDP(基于KCP),支持SSL,支持從內存字符串加載SSL證書;
  • TCP支持數據拆包功能(按指定的分隔符對數據自動進行拆包,保證用戶收到的數據是一個完整的數據包);實現了TCP的數據報模式(類似WEBSOCKET);
  • 支持windows,linux,32位,64位;
  • 依賴asio(boost::asio或獨立asio均可,若需要HTTP功能必須使用boost::asio),依賴C++17;
  • 代碼采用hpp頭文件方式,以源碼級鏈入,無需編譯,只需在工程的Include包含目錄中添加asio2路徑,然后在源碼中#include 包含頭文件即可;
  • demo目錄包含大量的示例工程(工程基于VS2017創建),各種使用方法請參考示例代碼;

TCP:

服務端:

asio2::tcp_server server;
server.bind_recv([&server](std::shared_ptr & session_ptr, std::string_view s)
{
????session_ptr->no_delay(true);
????printf("recv : %u %.*s\n", (unsigned)s.size(), (int)s.size(), s.data());
????// 異步發送(所有發送操作都是異步且線程安全的)
    session_ptr->send(s);
    // 發送時指定一個回調函數,當發送完成后會調用此回調函數,bytes_sent表示實際發送的字節數,
    // 發送是否有錯誤可以用asio2::get_last_error()函數來獲取錯誤碼
    // session_ptr->send(s, [](std::size_t bytes_sent) {});
}).bind_connect([&server](auto & session_ptr)
{
????printf("client enter : %s %u %s %u\n",
????session_ptr->remote_address().c_str(), session_ptr->remote_port(),
????????session_ptr->local_address().c_str(), session_ptr->local_port());
????// 可以用session_ptr這個會話啟動一個定時器,這個定時器是在這個session_ptr會話的數據收
????// 發線程中執行的,這對于連接狀態的判斷或其它需求很有用(尤其在UDP這種無連接的協議中,有
????// 時需要在數據處理過程中使用一個定時器來延時做某些操作,而且這個定時器還需要和數據處理
????// 在同一個線程中安全觸發)
????//session_ptr->start_timer(1, std::chrono::seconds(1), []() {});
}).bind_disconnect([&server](auto & session_ptr)
{
	printf("client leave : %s %u %s\n",
		session_ptr->remote_address().c_str(),
		session_ptr->remote_port(), asio2::last_error_msg().c_str());
});
server.start("0.0.0.0", "8080");
//server.start("0.0.0.0", "8080", '\n'); // 按\n自動拆包(可以指定任意字符)
//server.start("0.0.0.0", "8080", "\r\n"); // 按\r\n自動拆包(可以指定任意字符串)
//server.start("0.0.0.0", "8080", match_role('#')); // 按match_role指定的規則自動拆包(match_role請參考demo代碼)(用于對用戶自定義的協議拆包)
//server.start("0.0.0.0", "8080", asio::transfer_exactly(100)); // 每次接收固定的100字節
//server.start("0.0.0.0", "8080", asio2::use_dgram); // 數據報模式的TCP,無論發送多長的數據,雙方接收的一定是相應長度的整包數據

客戶端:

asio2::tcp_client client;
client.bind_connect([&](asio::error_code ec)
{
	if (asio2::get_last_error())
		printf("connect failure : %d %s\n", asio2::last_error_val(), asio2::last_error_msg().c_str());
	else
		printf("connect success : %s %u\n", client.local_address().c_str(), client.local_port());

	client.send("");
}).bind_disconnect([](asio::error_code ec)
{
	printf("disconnect : %d %s\n", asio2::last_error_val(), asio2::last_error_msg().c_str());
}).bind_recv([&](std::string_view sv)
{
	printf("recv : %u %.*s\n", (unsigned)sv.size(), (int)sv.size(), sv.data());

	client.send(sv);
})
	//.bind_recv(on_recv) // 綁定全局函數
	//.bind_recv(std::bind(&listener::on_recv, &lis, std::placeholders::_1)) // 綁定成員函數(具體請查看demo代碼)
	//.bind_recv(&listener::on_recv, lis) // 按lis對象的引用來綁定成員函數(具體請查看demo代碼)
	//.bind_recv(&listener::on_recv, &lis) // 按lis對象的指針來綁定成員函數(具體請查看demo代碼)
	;
client.async_start("0.0.0.0", "8080"); // 異步連接服務端
//client.start("0.0.0.0", "8080"); // 同步連接服務端
//client.async_start("0.0.0.0", "8080", '\n'); // 按\n自動拆包(可以指定任意字符)
//client.async_start("0.0.0.0", "8080", "\r\n"); // 按\r\n自動拆包(可以指定任意字符串)
//client.async_start("0.0.0.0", "8080", match_role); // 按match_role指定的規則自動拆包(match_role請參考demo代碼)(用于對用戶自定義的協議拆包)
//client.async_start("0.0.0.0", "8080", asio::transfer_exactly(100)); // 每次接收固定的100字節
//client.start("0.0.0.0", "8080", asio2::use_dgram); // 數據報模式的TCP,無論發送多長的數據,雙方接收的一定是相應長度的整包數據
// 發送時也可以指定use_future參數,然后通過返回值future來阻塞等待直到發送完成,發送結果的錯誤碼和發送字節數
// 保存在返回值future中(注意,不能在通信線程中用future去等待,這會阻塞通信線程進而導致死鎖)
// std::future> future = client.send("abc", asio::use_future); 

UDP:

服務端:

asio2::udp_server server;
// ... 綁定監聽器(請查看demo代碼)
server.start("0.0.0.0", "8080"); // 常規UDP
//server.start("0.0.0.0", "8080", asio2::use_kcp); // 可靠UDP

客戶端:

asio2::udp_client client;
// ... 綁定監聽器(請查看demo代碼)
client.start("0.0.0.0", "8080");
//client.async_start("0.0.0.0", "8080", asio2::use_kcp); // 可靠UDP

RPC:

服務端:

asio2::rpc_server server;
// ... 綁定監聽器(請查看demo代碼)
A a; // A的定義請查看demo代碼
server.bind("add", add); // 綁定RPC全局函數
server.bind("mul", &A::mul, a); // 綁定RPC成員函數
server.bind("cat", [&](const std::string& a, const std::string& b) { return a + b; }); // 綁定lambda表達式
server.bind("get_user", &A::get_user, a); // 綁定成員函數(按引用)
server.bind("del_user", &A::del_user, &a); // 綁定成員函數(按指針)
//server.start("0.0.0.0", "8080", asio2::use_dgram); // 使用TCP數據報模式作為RPC通信底層支撐,啟動服務端時必須要使用use_dgram參數
server.start("0.0.0.0", "8080"); // 使用websocket作為RPC通信底層支撐(需要到rcp_server.hpp文件末尾代碼中選擇使用websocket)

客戶端:

asio2::rpc_client client;
// ... 綁定監聽器(請查看demo代碼)
//client.start("0.0.0.0", "8080", asio2::use_dgram); // 使用TCP數據報模式作為RPC通信底層支撐,啟動服務端時必須要使用use_dgram參數
client.start("0.0.0.0", "8080"); // 使用websocket作為RPC通信底層支撐
asio::error_code ec;
// 同步調用RPC函數
int sum = client.call(ec, std::chrono::seconds(3), "add", 11, 2);
printf("sum : %d err : %d %s\n", sum, ec.value(), ec.message().c_str());
// 異步調用RPC函數,第一個參數是回調函數,當調用完成或超時會自動調用該回調函數,如果超時或其它錯誤,
// 錯誤碼保存在ec中,這里async_call沒有指定返回值類型,則lambda表達式的第二個參數必須要指定類型
client.async_call([](asio::error_code ec, int v)
{
	printf("sum : %d err : %d %s\n", v, ec.value(), ec.message().c_str());
}, "add", 10, 20);
// 這里async_call指定了返回值類型,則lambda表達式的第二個參數可以為auto類型
client.async_call([](asio::error_code ec, auto v)
{
	printf("sum : %d err : %d %s\n", v, ec.value(), ec.message().c_str());
}, "add", 12, 21);
// 返回值為用戶自定義數據類型(user類型的定義請查看demo代碼)
user u = client.call(ec, "get_user");
printf("%s %d ", u.name.c_str(), u.age);
for (auto &[k, v] : u.purview)
{
	printf("%d %s ", k, v.c_str());
}
printf("\n");

u.name = "hanmeimei";
u.age = ((int)time(nullptr)) % 100;
u.purview = { {10,"get"},{20,"set"} };
// 如果RPC函數的返回值為void,則用戶回調函數只有一個參數即可
client.async_call([](asio::error_code ec)
{
}, "del_user", std::move(u));

HTTP:

服務端:

asio2::http_server server;
server.bind_recv([&](std::shared_ptr & session_ptr, http::request& req)
{
    // 在收到http請求時嘗試發送一個文件到對端
    {
        // 如果請求是非法的,直接發送錯誤信息到對端并返回
        if (req.target().empty() ||
        req.target()[0] != '/' ||
        req.target().find("..") != beast::string_view::npos)
        {
            session_ptr->send(http::make_response(http::status::bad_request, "Illegal request-target"));
            session_ptr->stop(); // 同時直接斷開這個連接
            return;
        }

        // Build the path to the requested file
        std::string path(req.target().data(), req.target().size());
        path.insert(0, std::filesystem::current_path().string());
        if (req.target().back() == '/')
            path.append("index.html");

        // 打開文件
        beast::error_code ec;
        http::file_body::value_type body;
        body.open(path.c_str(), beast::file_mode::scan, ec);

        // 如果打開文件失敗,直接發送錯誤信息到對端并直接返回
        if (ec == beast::errc::no_such_file_or_directory)
        {
            session_ptr->send(http::make_response(http::status::not_found,
            std::string_view{ req.target().data(), req.target().size() }));
            return;
        }

        // Cache the size since we need it after the move
        auto const size = body.size();

        // 生成一個文件形式的http響應對象,然后發送給對端
        http::response res{
        std::piecewise_construct,
        std::make_tuple(std::move(body)),
        std::make_tuple(http::status::ok, req.version()) };
        res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
        res.set(http::field::content_type, http::extension_to_mimetype(path));
        res.content_length(size);
        res.keep_alive(req.keep_alive()); 
        res.chunked(true);
        // Specify a callback function when sending
        //session_ptr->send(std::move(res));
        session_ptr->send(std::move(res), [&res](std::size_t bytes_sent)
        {
            auto opened = res.body().is_open(); std::ignore = opened;
            auto err = asio2::get_last_error(); std::ignore = err;
        });
        //session_ptr->send(std::move(res), asio::use_future);
        return;
    }

    std::cout << req << std::endl;
    if (true)
    {
        // 用make_response生成一個http響應對象,狀態碼200表示操作成功,"suceess"是HTTP消息的body部分內容
        auto rep = http::make_response(200, "suceess");
        session_ptr->send(rep, []()
        {
            auto err = asio2::get_last_error(); std::ignore = err;
        });
    }
    else
    {
        // 也可以直接發送一個http標準響應字符串,內部會將這個字符串自動轉換為http響應對象再發送出去
        std::string_view rep =
            "HTTP/1.1 404 Not Found\r\n"\
            "Server: Boost.Beast/181\r\n"\
            "Content-Length: 7\r\n"\
            "\r\n"\
            "failure";
        // test send string sequence, the string will automatically parsed into a standard http request
        session_ptr->send(rep, [](std::size_t bytes_sent)
        {
            auto err = asio2::get_last_error(); std::ignore = err;
        });
    }
});
server.start(host, port);

客戶端:

asio2::error_code ec;
auto req1 = http::make_request("http://www.baidu.com/get_user?name=a"); // 通過URL字符串生成一個http請求對象
auto req2 = http::make_request("GET / HTTP/1.1\r\nHost: 127.0.0.1:8443\r\n\r\n"); // 通過http協議字符串生成一個http請求對象
req2.set(http::field::timeout, 5000); // 給請求設置一個超時時間
auto rep1 = asio2::http_client::execute("http://www.baidu.com/get_user?name=a", ec); // 通過URL字符串直接請求某個網址,返回結果在rep1中,如果有錯誤,錯誤碼保存在ec中
auto rep2 = asio2::http_client::execute("127.0.0.1", "8080", req2); // 通過IP端口以及前面生成的req2請求對象來發送一個http請求
std::cout << rep2 << std::endl; // 顯示http請求結果
std::stringstream ss;
ss << rep2;
std::string result = ss.str(); // 通過這種方式將http請求結果轉換為字符串

 

其它的HTTP使用方式以及WEBSOCKET使用方式請參考demo代碼

?

ICMP:

class ping_test // 模擬在一個類對象中使用ping組件(其它所有如TCP/UDP/HTTP等組件一樣可以在類對象中使用)
{
    asio2::ping ping;
public:
    ping_test() : ping(10) // 構造函數傳入的10表示只ping 10次后就結束,傳入-1表示一直ping
    {
        ping.timeout(std::chrono::seconds(3)); // 設置ping超時
        ping.interval(std::chrono::seconds(1)); // 設置ping間隔
        ping.body("0123456789abcdefghijklmnopqrstovuxyz");
        ping.bind_recv(&ping_test::on_recv, this) // 綁定當前這個類的成員函數作為監聽器
            .bind_start(std::bind(&ping_test::on_start, this, std::placeholders::_1)) // 也是綁定成員函數
            .bind_stop([this](asio::error_code ec) { this->on_stop(ec); }); // 綁定lambda
    }
    void on_recv(asio2::icmp_rep& rep)
    {
        if (rep.lag.count() == -1) // 如果延時的值等于-1表示超時了
            std::cout << "request timed out" << std::endl;
        else
            std::cout << rep.total_length() - rep.header_length()
                << " bytes from " << rep.source_address()
                << ": icmp_seq=" << rep.sequence_number()
                << ", ttl=" << rep.time_to_live()
                << ", ms"
                << std::endl;
    }
    void on_start(asio::error_code ec)
    {
        printf("start : %d %s\n", asio2::last_error_val(), asio2::last_error_msg().c_str());
    }
    void on_stop(asio::error_code ec)
    {
        printf("stop : %d %s\n", asio2::last_error_val(), asio2::last_error_msg().c_str());
    }
    void run()
    {
        if (!ping.start("127.0.0.1"))
        //if (!ping.start("123.45.67.89"))
        //if (!ping.start("stackoverflow.com"))
            printf("start failure : %s\n", asio2::last_error_msg().c_str());
        while (std::getchar() != '\n');
        ping.stop();
        // ping結束后可以輸出統計信息,包括丟包率,平均延時時長等
        printf("loss rate : %.0lf%% average time : %lldms\n", ping.plp(),
            std::chrono::duration_cast(ping.avg_lag()).count());
    }
};

?

SSL:?

TCP/HTTP/WEBSOCKET均支持SSL功能(需要在config.hpp中將#define ASIO2_USE_SSL宏定義放開)

asio2::tcps_server server;
// 從內存字符串加載SSL證書(具體請查看demo代碼)
server.set_cert("test", cer, key, dh); // cer,key,dh這三個字符串的定義請查看demo代碼
// 從文件加載SSL證書
//server.set_cert_file("test", "server.crt", "server.key", "dh512.pem");

  

TCP/HTTP/WEBSOCKET服務端、客戶端等SSL功能請到DEMO代碼中查看。

  

串口:

請查看demo示例代碼serial port 部分

?

其它:

定時器

// 框架中提供了定時器功能,使用非常簡單,如下:
asio2::timer timer;
// 參數1表示定時器ID,參數2表示定時器間隔,參數3為定時器回調函數
timer.start_timer(1, std::chrono::seconds(1), [&]()
{
    printf("timer 1\n");
    if (true) // 滿足某個條件時關閉定時器,當然也可以在其它任意地方關閉定時器
        timer.stop_timer(1);
});

  

還有其它一些輔助類的功能,請在源碼或使用中去體會吧.

?

?

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評論

请按住滑块,拖动到最右边
了解新功能

查看更多

广告

下載排行

本周

  1. 1Eurotherm TKS Temperature 用戶手冊
  2. 1.46 MB  |  2次下載  |  免費
  3. 2無線系統中天線和RF元件電磁建模
  4. 7.48 MB   |  1次下載  |  4 積分
  5. 3納祥科技NX6806中文規格書,8位AD和DA單片機拓展,國產替代PCF8591
  6. 3.04 MB  |  1次下載  |  免費
  7. 4藍牙無線遙控小車
  8. 10.49 MB   |  1次下載  |  2 積分
  9. 5Multisim模擬電路仿真教程
  10. 1.93 MB   |  1次下載  |  3 積分
  11. 6MNGate系列智能網關詳細使用手冊
  12. 11.62 MB   |  次下載  |  2 積分
  13. 7PC3302 7V 1.5A 1.25MHz升壓10白光LED驅動器英文手冊
  14. 1.04 MB   |  次下載  |  免費
  15. 8FCO-3C-WT|超寬溫晶體振蕩器
  16. 4.87 MB  |  次下載  |  免費

本月

  1. 1晶體三極管的電流放大作用詳細說明
  2. 0.77 MB   |  32次下載  |  2 積分
  3. 2Python從入門到精通背記手冊
  4. 18.77 MB   |  25次下載  |  1 積分
  5. 3雙極型三極管放大電路的三種基本組態的學習課件免費下載
  6. 4.03 MB   |  23次下載  |  1 積分
  7. 4多級放大電路的學習課件免費下載
  8. 1.81 MB   |  21次下載  |  2 積分
  9. 5九陽豆漿機高清原理圖
  10. 2.47 MB   |  16次下載  |  1 積分
  11. 61875功放原理圖
  12. 0.04 MB   |  11次下載  |  免費
  13. 7SW6306V AACC四口多協議升降壓移動電源SOC中文手冊
  14. 1.20 MB   |  10次下載  |  1 積分
  15. 8東芝彩色電視機29SF6C維修說明書
  16. 4.86 MB   |  9次下載  |  1 積分

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935127次下載  |  10 積分
  3. 2開源硬件-PMP21529.1-4 開關降壓/升壓雙向直流/直流轉換器 PCB layout 設計
  4. 1.48MB  |  420063次下載  |  10 積分
  5. 3Altium DXP2002下載入口
  6. 未知  |  233089次下載  |  10 積分
  7. 4電路仿真軟件multisim 10.0免費下載
  8. 340992  |  191382次下載  |  10 積分
  9. 5十天學會AVR單片機與C語言視頻教程 下載
  10. 158M  |  183337次下載  |  10 積分
  11. 6labview8.5下載
  12. 未知  |  81585次下載  |  10 積分
  13. 7Keil工具MDK-Arm免費下載
  14. 0.02 MB  |  73814次下載  |  10 積分
  15. 8LabVIEW 8.6下載
  16. 未知  |  65988次下載  |  10 積分
主站蜘蛛池模板: 久久精品视在线-2 | 浪荡女天天不停挨CAO日常视 | 国产精品久久高潮呻吟无码 | 国产欧美另类久久久品 | 超碰caopro熟女m超碰分类 | 在线电影一区二区 | 在教室伦流澡到高潮H免费视频 | 一本一本之道高清在线观看 | 被公疯狂玩弄的漂亮人妻 | 亚洲成人免费在线观看 | 福利一区福利二区 | 99精品观看 | 一个人免费视频在线观看 | 337p欧洲亚大胆精品 | 国产盗摄TP摄像头偷窥 | 99热久久这里只有精品 | 特黄大片aaaaa毛片 | 羞羞影院午夜男女爽爽免费 | 国语92电影网午夜福利 | 亚洲乱码国产一区三区 | 青青草原直播 | 法国剧丝袜情版h级在线电影 | 亚洲一区二区三区91 | 黄色软件色多多 | 美女在线永久免费网站 | 我在厨房摸岳的乳HD在线观看 | 5G年龄确认我已满18免费 | 美女岔开腿露出粉嫩花苞 | 精品国产人成亚洲区 | 国产SUV精品一区二区69 | 精品国产自在天天线2019 | 亚洲人成伊人成综合网久久久 | 久久re视频这里精品09免费 | 凌晨三点免费WWW | 很很射影院 | 亚洲三级在线观看 | 性虎成人网 | 37pao成人国产永久免费视频 | 天天躁日日躁狠狠躁午夜剧场 | 久久成人无码国产免费播放 | 日本人bbwbbwbbwbbw|