1. 程式人生 > >C++ 協程與網路程式設計

C++ 協程與網路程式設計

協程

協程,即協作式程式,其思想是,一系列互相依賴的協程間依次使用CPU,每次只有一個協程工作,而其他協程處於休眠狀態。協程可以在執行期間的某個點上暫停執行,並在恢復執行時從暫停的點上繼續執行。 
協程已經被證明是一種非常有用的程式元件,不僅被python、lua、ruby等指令碼語言廣泛採用,而且被新一代面向多核的程式語言如golang rust-lang等採用作為併發的基本單位。 
協程可以被認為是一種使用者空間執行緒,與傳統的執行緒相比,有2個主要的優點:

  • 與執行緒不同,協程是自己主動讓出CPU,並交付他期望的下一個協程執行,而不是在任何時候都有可能被系統排程打斷。因此協程的使用更加清晰易懂,並且多數情況下不需要鎖機制。
  • 與執行緒相比,協程的切換由程式控制,發生在使用者空間而非核心空間,因此切換的代價非常小。

網路程式設計模型

首先來簡單回顧一下一些常用的網路程式設計模型。網路程式設計模型可以大體的分為同步模型和非同步模型兩類。

  • 同步模型:

同步模型使用阻塞IO模式,在阻塞IO模式下呼叫read等IO函式時會阻塞執行緒直到IO完成或失敗。

同步模型的典型代表是thread per connection模型,每當阻塞在主執行緒上的accept呼叫返回時則建立一個新的執行緒去服務於新的socket的讀/寫。這種模型的優點是程式簡潔,編寫簡單;缺點是可伸縮性收到執行緒數的限制,當連線越來越多時,執行緒也越來越多,頻繁的執行緒切換會嚴重拖累效能。

  • 非同步模型:

非同步模型一般使用非阻塞IO模式,並配合epoll/select/poll等多路複用機制。在非阻塞模式下呼叫read,如果沒有資料可讀則立即返回並通知使用者沒有可讀(EAGAIN/EWOULDBLOCK),而非阻塞當前執行緒。非同步模型可以使一個執行緒同時服務於多個IO物件。

非同步模型的典型代表是reactor模型。在reactor模型中,我們將所有要處理的IO事件註冊到一箇中心的IO多路複用器中(一般為epoll/select/poll),同時主執行緒阻塞在多路複用器上。一旦有IO事件到來或者就緒,多路複用器返回並將對應的IO事件分發到對應的處理器(即回撥函式)中,最後處理器呼叫read/write函式來進行IO操作。

非同步模型的特點是效能和可伸縮性比同步模型要好很多,但是其結構複雜,不易於編寫和維護。在非同步模型中,IO之前的程式碼(IO任務的提交者)和IO之後的處理程式碼(回撥函式)是割裂開來的。

協程與網路程式設計

協程為克服同步模型和非同步模型的缺點,並結合他們的優點提供了可能:

首先簡單認識一下排程器:一個執行緒執行一個排程器,可以在一個排程器上建立若干個協程。排程器負責排程這些協程。並且排程器在其內部維護了一個多路複用器(epoll/select/poll)。

現在假設我們有3個協程A,B,C分別要進行數次IO操作。這3個協程執行在同一個排程器(執行緒)的上下文中,並依次使用CPU。

協程A首先執行,當它執行到一個IO操作,但該IO操作並沒有立即就緒時,A將該IO事件註冊到排程器中,並主動放棄CPU。這時排程器將B切換到CPU上開始執行,同樣,當它碰到一個IO操作的時候將IO事件註冊到排程器中,並主動放棄CPU。排程器將C切換到cpu上開始執行。當所有協程都被“阻塞”後,排程器檢查註冊的IO事件是否發生或就緒。假設此時協程B註冊的IO事件已經就緒,排程器將恢復B的執行,B將從上次放棄CPU的地方接著向下執行。A和C同理。

這樣,對於某個協程而言,我們採用的是同步的模型;但是對於整個排程器(執行緒)而言,實際上卻是非同步的模型。

好了,原理說完了,我們來看一個實際的例子,echo server。

echo server

在這個例子中,我們將使用orchid庫來編寫一個echo server。orchid庫是一個構建於boost基礎上的 協程/網路IO 庫。

echo server首先必須要處理連線事件,我們建立一個協程來專門處理連線事件:

01 typedef boost::shared_ptr<orchid::socket> socket_ptr;
02 //處理ACCEPT事件的協程
03 void handle_accept(orchid::coroutine_handle co) {
04 try {
05 orchid::acceptor acceptor(co -> get_scheduler().get_io_service());//構建一個acceptor
06 acceptor.bind_and_listen("5678",true);
07 for(;;) {
08 socket_ptr sock(new orchid::socket(co -> get_scheduler().get_io_service()));
09 acceptor.accept(*sock,co);
10 co -> get_scheduler().spawn(boost::bind(handle_io,_1,sock),orchid::minimum_stack_size());//在排程器上建立一個協程來服務新的socket。
11 //第一個引數是要建立的協程的main函式,
12 //第二個引數是要建立的協程的棧的大小。

相關推薦

C++ 網路程式設計

協程 協程,即協作式程式,其思想是,一系列互相依賴的協程間依次使用CPU,每次只有一個協程工作,而其他協程處於休眠狀態。協程可以在執行期間的某個點上暫停執行,並在恢復執行時從暫停的點上繼續執行。  協程已經被證明是一種非常有用的程式元件,不僅被python、l

C#精通C#程式設計:玩轉開發例項...C#程式設計入門、C#程式設計例項、C#開發例項網路程式設計等....

            C#是微軟公司釋出的一種面向物件的、運行於.NET Framework之上的高階程式設計語言。並定於在微軟職業開發者論壇(PDC)上登臺亮相。C#是微軟公司研究員Anders Hejlsberg的最新成果。C#看起來與Java有著驚人的相似;它包

C# 逆變

允許 隱式 逆變 visual 類型轉換 委托 種類 保留 泛型 協變與逆變相信大家都不陌生,但是大多數人,可能都不明白其具體的含義,包括我本人,所以今天打算詳細的介紹下C#的協變與逆變。 1、概念簡介 在C#和Visual Basic中,協變和逆變允許以下三種類型的參數進

Python開發——15.I/O模型

沒有 mage F5 quest 資源 輸入數據 準備 cor 異步 一、協程(Coroutine) 1.知識背景 協程又稱微線程,是一種用戶態的輕量級線程。子程序,或者稱為函數,在所有語言中都是層級調用,比如A調用B,B在執行過程中又調用了C,C執行完畢返回,B執行完畢返

【PYTHON模塊】:greenlet、gevent

left imp test bind lse 調用 編程模型 send 地址 協程:又稱為微線程,英文名稱Coroutine。作用:它擁有自己的寄存器上下文和棧,能保留上一次調用時的狀態,可以隨時暫停程序,隨時切換回來。優點: ?無需線程上下文切換的開銷 ?無需

C/C++的實現方式總結

創建 his pre dto spa -s pro 跳轉 保存 1、利用 C 語言的 setjmp 和 longjmp,函數中使用 static local 的變量來保存協程內部的數據。 函數原型:int setjmp(jmp_buf envbuf);

(轉)通過組合語言實現C

轉自:http://www.cnblogs.com/sniperHW/archive/2012/06/19/2554574.html 協程的概念就不介紹了,不清楚的同學可以自己google,windows和unix like系統本身就提供了協程的支援,windows下叫fiber,unix like系統下叫

(轉)通過匯編語言實現C

mov fine ext https context nbsp make oid reat 轉自:http://www.cnblogs.com/sniperHW/archive/2012/06/19/2554574.html 協程的概念就不介紹了,不清楚的同學可以自己goo

Pythonasyncio

asyncio(解決非同步io程式設計的一整套解決方案,它主要用於非同步網路操作、併發和協程)協程(Coroutine一種使用者態的輕量級微執行緒,它是程式級別的,在執行過程中可以中斷去執行其它的子程式,別的子程式也可以中斷回來繼續執行之前的子程式,無需執行緒上下文切換的開銷) get_event_loop

[譯]C++ :理解 co_await 運算子

原文地址:C++ Coroutines: Understanding operator co_await 原文作者:lewissbaker 譯文出自:掘金翻譯計劃 本文永久連結:github.com/xitu/gold-m… 譯者:7Ethan 校對者:razert

swoole go 對比

date: 2018-5-30 14:31:38 title: swoole| swoole 協程初體驗 description: 通過協程的執行初窺 swoole 中協程的排程; 理解協程為什麼快; swoole 協程和 go 協程對比 折騰 swoole 協程有一段時間了, 總結一篇入門貼,

golang語言漸入佳境[20]-通道

協程引入 通過狀態檢查器checkLink,不斷的獲取切片當中的網址,並且列印了出來。順序執行。這也就意味著,一旦我訪問google.com等網站就會陷入到等待的狀況中。後面的網址無法訪問。 1234567891011121314151617181920212223242526

C語言:Winsock網路程式設計—ping命令的簡單實現

Winsock網路程式設計—ping命令的簡單實現 前言 先宣告 博主實現的是Windows平臺的ping命令的簡單實現,沒有做域名解析,只能直接ping ip。我們要實現ping 肯定得先知道ping的實現原理,ping 傳送的 ICMP報文。實際上的落腳點 就是對 ICMP協

異常網路程式設計

new 和init的區別 __new__比__init__先執行,其作用是建立一個空的類物件 作為一個類物件:必須具有三個組成部分 所以呼叫type中的__new__來完成組裝 得到這個類物件後需要將其返回,以供__init__來使用   異常: 程式中無法按照邏輯順序執行完全部程式碼

Unity3d中C#的幾種呼叫方式

協程使用IEnumerator修飾符,yield return返回 第一種方式: .IEnumerator Start()     {         Debug.Log ("開始等待:" + Time.time);         yield return new

Tornado異步之-回調

tin sync value out 網絡 mark comm 請求 clas 回調處理異步請求 回調 callback 處理異步官方例子 # 導入所需庫 from tornado.httpclient import AsyncHTTPClient def asyn

Tornado非同步之-回撥

回撥處理非同步請求 回撥 callback 處理非同步官方例子 # 匯入所需庫 from tornado.httpclient import AsyncHTTPClient def asynchronous_fetch(url, callback): http

Linux C基於TCP的網路程式設計(三次握手)

網路通訊(TCP) TCP(面向連線的通訊協議):在通訊中時刻保持連線,這種通訊方式類似於打電話,能保證安全可靠資料不丟失,但是與UDP相比傳輸速度較低。 TCP和UDP通訊收發函式區別:記住socket中是否存放有IP 和埠資訊,TCP有,UDP無。同時T

python同步

協程與非同步   協程簡介:   協程又稱之為微執行緒,協程看上去也是子程式,但在執行的過程中,在子程式內部可中斷,然後轉而執行別的子程式,在適當的時候返回來接著執行程式。當然子程式是協程的特列。  個人見解:協程相當與在子程式(假設稱之為A程式)執行的過程中執行到一定的步驟後可以進

Python 多工排程

協程與多工排程 時間 2016-03-31 23:02:15 IT技術部落格大學習 原文 在電腦科學中,多工(multitasking)是指在同一個時間段內執行多個任務,現代計算機作為一個複雜的系統,執行的任務往往不止一個,所以多工排程對於計算機來說尤為重要。現階段