1. 程式人生 > >boost::asio 非同步超時機制一

boost::asio 非同步超時機制一

#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/read_until.hpp>
#include <boost/asio/streambuf.hpp>
#include <boost/asio/write.hpp>
#include <boost/bind.hpp>
#include <iostream>

using boost::asio::deadline_timer;
using boost::asio::ip::tcp;


class client
{
public:
	// 在建構函式的初始化列表中 初始化所有變數
	client(boost::asio::io_service& io_service)
		: stopped_(false),
		socket_(io_service),
		deadline_(io_service),
		heartbeat_timer_(io_service)
	{
	}

	// 對外公開並使用的唯一介面
	// 
	void start(tcp::resolver::iterator endpoint_iter)
	{
		// 連線server
		start_connect(endpoint_iter);

		// 設定連線超時間,並指定回撥函式
		deadline_.async_wait(boost::bind(&client::check_deadline, this));
	}

private:
	void stop()
	{
		stopped_ = true;
		boost::system::error_code ignored_ec;
		socket_.close(ignored_ec);// 關閉socket
		deadline_.cancel();// 取消定時器
		heartbeat_timer_.cancel();
	}

	void start_connect(tcp::resolver::iterator endpoint_iter)
	{
		if (endpoint_iter != tcp::resolver::iterator())
		{
			std::cout << "Trying " << endpoint_iter->endpoint() << "...\n";

			// 設定定時器超時時間
			deadline_.expires_from_now(boost::posix_time::seconds(60));

			// 設定連線成功回撥函式
			socket_.async_connect(endpoint_iter->endpoint(),
				boost::bind(&client::handle_connect,
				this, _1, endpoint_iter));
		}
		else
		{
			stop();
		}
	}

	void handle_connect(const boost::system::error_code& ec,
		tcp::resolver::iterator endpoint_iter)
	{
		if (stopped_)
			return;

		if (!socket_.is_open())
		{
			std::cout << "Connect timed out\n";

			start_connect(++endpoint_iter);
		}
		else if (ec)
		{// 其他方面的錯誤 如伺服器沒有開啟
			std::cout << "Connect error: " << ec.message() << "\n";

			socket_.close();

			start_connect(++endpoint_iter);
		}
		else
		{// 連線成功
			std::cout << "Connected to " << endpoint_iter->endpoint() << "\n";

			start_read();

			start_write();// 開始心跳
		}
	}

	void start_read()
	{
		// 設定recv 超時時間,此處會觸發 check_deadline 但不是真正的超時
		deadline_.expires_from_now(boost::posix_time::seconds(30));

		// 非同步接收以"\n"為結束符/  意為從網路快取中讀取一行
		boost::asio::async_read_until(socket_, input_buffer_, '\n',
			boost::bind(&client::handle_read, this, _1));
	}

	void handle_read(const boost::system::error_code& ec)
	{
		if (stopped_)
			return;

		if (!ec)
		{
			std::string line;
			std::istream is(&input_buffer_);
			std::getline(is, line);// 從流中獲取一行內容  捨去回車

			if (!line.empty())// 如果line.empty == true 是表示是一個心跳包,心跳包只發送一個回車\n
			{
				std::cout << "Received: " << line << "\n";
			}

			// 開始新一次讀取
			start_read();
		}
		else
		{// 讀取發生錯誤/ 遠端已關閉socket
			std::cout << "Error on receive: " << ec.message() << "\n";

			stop();
		}
	}


	//////////////////////////////////////////////////////////////////////////
	// 定時器完成心跳
	void start_write()
	{
		if (stopped_)
			return;

		// Start an asynchronous operation to send a heartbeat message.
		boost::asio::async_write(socket_, boost::asio::buffer("\n", 1),
			boost::bind(&client::handle_write, this, _1));
	}

	void handle_write(const boost::system::error_code& ec)
	{
		if (stopped_)
			return;

		if (!ec)
		{
			// 設定超時時間
			heartbeat_timer_.expires_from_now(boost::posix_time::seconds(10));
			
			// 開始非同步等待,並設定超時回撥函式
			heartbeat_timer_.async_wait(boost::bind(&client::start_write, this));
		}
		else
		{
			std::cout << "Error on heartbeat: " << ec.message() << "\n";

			stop();
		}
	}
	//////////////////////////////////////////////////////////////////////////

	void check_deadline()
	{
		if (stopped_)// check 是存已標識並等待程式退出
			return;

		if (deadline_.expires_at() <= deadline_timer::traits_type::now())
		{// 真正的等待超時

			socket_.close();// 關閉對應的socket 包括連線超時/recv超時

			deadline_.expires_at(boost::posix_time::pos_infin);// 定時器 設定為永不超時/不可用狀態
		}

		// 如果不是真正的超時,定是其操作已成功/使用者重新設定了定時器
		// 重新啟動定時器
		deadline_.async_wait(boost::bind(&client::check_deadline, this));
	}

private:
	bool stopped_;								// 標識程式是否停止執行
	tcp::socket socket_;						// 
	boost::asio::streambuf input_buffer_;		// recv buf
	deadline_timer deadline_;					// 連線/recv 超時 定時器
	deadline_timer heartbeat_timer_;			// 心跳超時 計時器
};

int main(int argc, char* argv[])
{
	try
	{

		boost::asio::io_service io_service;
		tcp::resolver r(io_service);
		client c(io_service);

		c.start(r.resolve(tcp::resolver::query("127.0.0.1", "8889")));

		io_service.run();
	}
	catch (std::exception& e)
	{
		std::cerr << "Exception: " << e.what() << "\n";
	}

	return 0;
}

相關推薦

boost::asio 非同步超時機制

#include <boost/asio/deadline_timer.hpp> #include <boost/asio/io_service.hpp> #include <boost/asio/ip/tcp.hpp> #include

Boost Asio要點概述(

【注】本文不是boost asio的完整應用講述,而是僅對其中要點的講解,主要參考了Boost Asio 1.68的官方文件(https://www.boost.org/doc/libs/1_68_0/doc/html/boost_asio/overview.html),程式

boost asio非同步讀寫網路聊天室【官方示例】

// // chat_message.hpp // ~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distri

boost asio非同步讀寫網路聊天程式客戶端 例項詳解

// // chat_server.cpp // ~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boos

boost asio 非同步實現tcp通訊

一、前言 boost asio可算是一個簡單易用,功能又強大可跨平臺的C++通訊庫,效率也表現的不錯,linux環境是epoll實現的,而windows環境是iocp實現的。而tcp通訊是專案當中經常用到通訊方式之一,實現的方法有各式各樣,因此總結一套適用於自己專案的方法是

boost::asio 非同步主動連線多個伺服器

#include "ATC.hpp" namespace PWRD{     namespace Network{         //-------------------------------------------------------------------------

種極簡的非同步超時處理機制設計與實現(C#版)

1.引言 當執行某些動作之後,會期待反饋。最終要麼是得到了結果,要麼就是超時了。當超時發生時,可能是期望得到通知,或是希望能自動重試,等等。於是設計了一種通用的非同步超時的處理機制,以期通過簡潔易理解的方式完成超時的處理過程。 2.對外介面設計 從使用的角度,呼叫方期望的是“指定超時時長,時間到自動執行指定過

js執行機制非同步程式設計(

相信大家在面試的過程中經常遇到檢視執行順序的問題,如setTimeout,promise,async await等等,各種組合,是不是感覺頭都要暈掉了,其實這些問題最終還是考察大家對js的執行機制是否掌握牢固,對promise,async的原理是否掌握,萬變不離其宗,這次就來徹底搞懂它。 1 js引擎

基於c++的網路開發庫boost.Asio學習 () Ubuntu安裝boost以及問題解決

執行環境:Ubuntu 12.04   版本: boost 1.68 下載網址:http://sourceforge.net/projects/boost/files/boost/1.58.0/boost_1_58_0.tar.bz2/download

非同步服務端中的多執行緒 boost asio

這個demo程式好像會死鎖,哪位高手要是能找到原因麻煩告訴一下 // gogogo.cpp : Defines the entry point for the console application. // #include "stdafx.h" #ifdef WIN3

Boost.asio學習之Tcp非同步通訊Demo

    現在處於剛剛學了C++基礎語法,看別人的程式碼縷邏輯縷的慢,按自己的邏輯寫程式碼構思不太清楚漏洞百出。雖然boost asio程式設計已經學了一週,邏輯也差不多清楚,不過親手寫一個Demo會發現很多平時注意不到的小細節,往往這些小細節就是以後耽誤時間的主要原因。所以強

boost::asio阻塞等待與非同步等待

阻塞等待:這裡會等待3秒然後才進行輸出。 #include <iostream> #include <boost/asio.hpp> #include <boost/date_time/posix_time/posix_time.hpp>

boost::asio之()簡單客戶端服務器回顯功能

讀取 緩存 argc john sock n! return byte 服務 客戶端: // BoostDev.cpp: 定義控制臺應用程序的入口點。 // #include "stdafx.h" #include <iostream> #

Boost.Asio C++ 網路程式設計之十:基於TCP的非同步服務端

       這個流程圖是相當複雜的:從Boost.Asio出來你可以看到4個箭頭指向on_accept,on_read,on_write和on_check_ping。這也就意味著你永遠不知道哪個非同步呼叫是下一個完成的呼叫,但是你可以確定的是它是這4個操作中的一個。基於TC

Boost Asio庫的學習與探究(

對於boost庫的強大的能力,相信用過boost的人都知道。筆者作用一個小白,今天開始一一探究boost asio庫的一些東西,這裡著重探究和網路有關的內容。由於之前沒有看過asio的原始碼,這裡不免有疏漏和不足,甚至是錯誤之處,這裡歡迎大家一起來探討。 boost/asi

Boost.Asio C++ 網路程式設計之二:同步和非同步

       首先,非同步程式設計和同步程式設計是截然不同的。在同步程式設計中,所有的操作都是順序執行的,比如從socket中讀取(請求),然後寫入(迴應)到socket中。每一個操作都是阻塞的。因為操作是阻塞的,所以為了不影響主程式,當在socket上讀寫時,通常會建立一個

C++ Boost asio庫網路通訊 [同/非同步] 筆記

此文轉自:http://blog.csdn.net/misskissC/article/details/9985167 1 C++ Boost庫asio網路通訊類核心結構 在C++ Boost庫中用於通訊的類的層次為boost::asio::ip,所有有關通訊的類別都

基於Boost.Asio非同步通訊伺服器設計與開發

 boost::asio 通訊伺服器實踐 1.開發環境搭建 1.1.Asio準備 萬事開頭難。對於一個C++的陌生者,編譯一個開源的程式碼並不是一件輕鬆愉快的事情。為使大家在審閱和檢測本程式碼可使用性時沒有必要花費太多時間和精力去編譯Boost::Asio

【SpringCloud】(十):超時機制和斷路器及 Hystrix簡單實踐

  上篇文章我們配置了Eureka叢集,實現了高可用。在微服務框架中,一個服務消費者可能是其他服務消費者的提供者,而當低層次的服務提供者出現問題時,會導致系統資源被耗盡。出現雪崩效應。 Hystri

Boost.Asio C++ 網路程式設計之九:基於TCP的非同步客戶端

       現在,是比較有趣(也比較難)的非同步實現! 當檢視流程圖時,你需要知道Boost.Asio代表由Boost.Asio執行的一個非同步呼叫。例如do_read(),Boost.Asio和on_read()代表了從do_read()到on_read()的邏輯流程,