協程 gevent

舉一個例子,模擬一個tcp服務器處理30個客戶socket。
假設你是一個老師,讓30個學生解答一道題目,而後檢查學生作的是否正確,你有下面幾個選擇:react

  1. 第一種選擇:按順序逐個檢查,先檢查A,而後是B,以後是C、D。。。這中間若是有一個學生卡主,全班都會被耽誤。這種模式就比如,你用循環挨個處理socket,根本不具備併發能力。
  2. 第二種選擇:你建立30個分身,每一個分身檢查一個學生的答案是否正確。 這種相似於爲每個用戶建立一個進程或者線程處理鏈接。
  3. 第三種選擇,你站在講臺上等,誰解答完誰舉手。這時C、D舉手,表示他們解答問題完畢,你下去依次檢查C、D的答案,而後繼續回到講臺上等。此時E、A又舉手,而後去處理E和A。。。
    這種就是IO複用模型,Linux下的select、poll和epoll就是幹這個的。將用戶socket對應的fd註冊進epoll,而後epoll幫你監聽哪些socket上有消息到達,這樣就避免了大量的無用操做。此時的socket應該採用非阻塞模式。這樣,整個過程只在調用select、poll、epoll這些調用的時候纔會阻塞,收發客戶消息是不會阻塞的,整個進程或者線程就被充分利用起來,這就是事件驅動,所謂的reactor模式。

操做系統爲你提供了一個功能,當你的某個socket可讀或者可寫的時候,它能夠給你一個通知。這樣當配合非阻塞的socket使用時,只有當系統通知我哪一個描述符可讀了,我纔去執行read操做,能夠保證每次read都能讀到有效數據而不作純返回-1和EAGAIN的無用功。寫操做相似。操做系統的這個功能經過select/poll/epoll/kqueue之類的系統調用函數來使用,這些函數均可以同時監視多個描述符的讀寫就緒情況,這樣,多個描述符的I/O操做都能在一個線程內併發交替地順序完成,這就叫I/O多路複用,這裏的「複用」指的是複用同一個線程。服務器

socket

咱們知道兩個進程若是須要進行通信最基本的一個前提能可以惟一的標示一個進程,在本地進程通信中咱們可使用PID來惟一標示一個進程,但PID只在本地惟一,網絡中的兩個進程PID衝突概率很大,這時候咱們須要另闢它徑了,咱們知道IP層的ip地址能夠惟一標示主機,而TCP層協議和端口號能夠惟一標示主機的一個進程,這樣咱們能夠利用ip地址+協議+端口號惟一標示網絡中的一個進程。網絡

相關文章
相關標籤/搜索