Linux服務端編程經驗__html5

來源:互聯網
上載者:User

學習linux服務端編程的過程中跟一個擁有多年linux服務端編程經驗的前輩請教了一番,有的地方理解的或許沒有那麼透徹,

在這裡記錄一下,後期內功修鍊的差不多了再回來看看是否有新的理解。 主流伺服器模式 做過很多伺服器項目,看過很多源碼,現在主流伺服器都是Reactor模式,下面是一個簡單的epoll實現Reactor模式的例子 http://blog.csdn.net/rankun1/article/details/69938640
先用select或者poll、epoll分離出io事件  然後處理io事件(發送或者讀取網路資料) 最後對收到的資料進行解包
然後進行相應的處理,複雜一點的會將解好的資料包丟到一個任務隊列裡面去
阻塞和非阻塞 阻塞和非阻塞強調的是是否在程式處理耗時操作上等待 這兩個概念一般是對於IO或其它可能耗時等待的操作而言,我們這裡就io操作來分析: 無論是網路io還是檔案io,io描述符都可以設定為阻塞或者非阻塞的, 拿recv來舉例,io操作可以分為兩個步驟:第一個步驟是recv時判斷是否有資料,第二個步驟接收資料 阻塞io和非阻塞io的區別在於第一個步驟時 沒有資料的情況下(如果確定了有資料了,你再去recv,阻塞和非阻塞效果是一樣的) 對於阻塞的io:如果recv時有資料,則立即進行第二個步驟去接收完資料返回;發現沒有資料則recv函數阻塞等待,直到資料到來,接收資料recv函數返回 對於非阻塞的io:如果recv時有資料,則立即進行第二個步驟去接收完資料返回;發現沒有資料則recv直接返回-1 報錯,並返回一個錯誤碼碼WSAEWOULDBLOCK,表明不是真正的出錯,而是當前操作不能完成,也就是說沒有資料了。 總結: 在我們執行recv這個操作可能是需要耗時的(這個耗時主要指從沒有資料到資料到來這段時間,接收資料使用的時間這裡不考慮在內),在這段時間你希望程式在處理過程中等待嗎。沒有資料就阻塞在這裡等待,不執行其它操作,這是阻塞(對於connect來說,就是我不想阻塞等待直到connect完成,對於accept就是我不想阻塞等待直到accept完成)。我不想讓程式在這裡等待,我繼續處理別的操作,我過一會再來看看有沒有資料到來,這就是非阻塞。 select poll 在阻塞和非阻塞中提到一句話:如果確定了有資料了,你再去recv,阻塞和非阻塞效果是一樣的(很顯然啊,我到了肯定有資料,肯定不用在等資料到來上花時間),那麼如何確定有資料了呢。select poll就是幹這個的,監聽你的io描述符上是否有資料,有資料了就返回,還有一個好處是它們可以同時監聽多個io描述符(內部輪詢查看), 這就是io多工概念嗎。注意一點,select耗時與否在於你設定的逾時時間, 與你的io描述符是否阻塞沒有任何關係,不要混淆。 這裡是select poll詳細講解 http://blog.csdn.net/rankun1/article/details/69691950 select確定有資料後,一次接收多少合適。 首先 不一定要while收,也就是說 不一定要迴圈收,因為select出已經有資料了 
所以調用recv時 肯定能收到資料,至於一次性收多少 根據你個人喜歡 
假如伺服器發來100個位元組,你要收取200,沒關係,這次這能收到100個,recv傳回值是100
相反,如果100的位元組,你選擇收取50個位元組也沒關係,下一次調用select時因為socket上還有資料,還是會顯示該socket可讀
你再繼續收取。
select通知你一次後,如果你要迴圈recv,或者多次recv你要注意了,阻塞socket和非阻塞socket是有區別的, 因為select通知了你一次有資料之後,你多次recv的過程中,不知道哪次把資料收完了,就不確定下次有沒有資料可以recv了, 對於 沒有資料的情況當然阻塞和非阻塞有區別了,上面已經講了。 有多少資料收多少資料 繼續上面的話題,我可不可以提前知道當前socket可以recv多少,然後我就去recv多少呢。答案是可以的。

int ioctlsocket(  _In_    SOCKET s,  _In_    long   cmd,  _Inout_ u_long *argp);
可以通過這個函數,預Crowdsourced Security Testing道要收多少位元組。不過不常用
同步和非同步 我一開始對同步和非同步理解是這樣的:在io操作上,有回調通知的是非同步,沒有回調通知需要等待的是同步,這樣的理解太狹隘了, 這裡的同步和非同步是一個寬泛的概念,設定回調是非同步主流方式。(和多線程編程中的同步不是一個概念,不要混為一談)。 (以下同步非同步還沒有理解,此處標記,後面回頭再看看理解了再重新整理) 同步是代碼可能阻塞在某個流程上
舉例:
資料接收舉例:
設定收資料和實際收資料在流程上是順序的,這是同步
設定收資料和實際收資料是兩個不同的地方,這是非同步
connect舉例:
connect一般是阻塞的,等待它返回結果,就是同步
設定socket非阻塞模式 然後connect會立即返回,不用管了,
後面用select檢測socket是否可寫 如果可寫則串連上了,這是非同步
不阻塞等於非同步,

C++11 裡面的std::async 和std::future都是設定非同步好方法
總之,使用同步還是非同步根據自己的需求來,同步在流程上具有一致性,方便調試;非同步代碼具有跨越性,流程上可能不好理解,不方便調試
20171209更新: 同步和非同步在I/O模型中的概念和在併發模式中的概念是不同的: 在I/O模型中同步和非同步體現在收發資料是由誰(應用程式層還是核心)來做的,或者說IO事件發生時是通知的就緒事件還是完成事件:
同步IO:io讀寫事件觸發時,需要應用程式層自己去調用recv/send來收發資料,也就是說io事件發生時,是說明資料就緒了,可以去讀寫了 非同步IO:io讀寫事件觸發時,表明資料收發操作已經完成了,由核心來完成的,可以直接處理資料了 併發模式中的同步和非同步體現在程式的執行順序上: 同步指的是程式完全按照代碼序列的順序執行 非同步指的是程式執行需要由系統事件來驅動,常見系統事件包括中斷,訊號等。 水平觸發和邊緣觸發 level trigger和edge trigger,這是linux 2.6核心引入的概念,因為是隨epoll來的,windows上沒有這個概念 首先看一下select和epoll的區別 http://blog.csdn.net/rankun1/article/details/70227010 重複一下select和epoll區別: 1. select有控制代碼數目限制,windows平台就64個 ,而且是遍曆這些socket,演算法是O(n),集合越大效率越低, epoll的數量是系統最大控制代碼數目,這個只要系統記憶體夠用,基本上認為很多很多
2. select是主動輪詢,而epoll是作業系統通知你,如果沒有的話 epoll就掛在那裡,一個相當於線程空轉,一個相當於線程休眠
再說lt和et模式
比如一個socket只要可讀,lt模式就會觸發
對於et模式,一個socket上從沒有資料到有資料會觸發一次,如果沒收乾淨,下次不會再觸發了
解釋:
lt模式是只要fd上有訊號就會觸發,et是訊號改變才會觸發
這是電工學上的概念,高電平有訊號,低電平無訊號
lt是只要有訊號就觸發,et是在從低電平到高電平觸發一次

所以et模式下一定要把socket資料收乾淨,不然後面再也不會觸發資料可讀了 (同理,如果你這個socket是服務端監聽socket,那麼et模式下你要在迴圈裡accept處理完所有串連,要不然後面不會觸發用戶端串連了),也就是說放到一個迴圈裡面去,這就是本質區別

網路io處理和資料邏輯處理(解協議等)要放在不同的線程裡嗎? 處理網路io的線程稱為網路線程,一般是迴圈阻塞在epoll_wait上的,等epoll_wait觸發後去接收資料或者接收用戶端串連, 收到的資料可以放在單獨的線程裡去解包,也可以讓閒置網路線程去做。因為有的時候,大多數網路線程是閒置。當然這要根據你的伺服器應用情境 來決定你用哪種方式去解包。有可能你的資料很小,但是用戶端很多,有可能你用戶端不多,但是資料互動很頻繁等情況。看看你是注重哪種商務邏輯。 這裡說一下讓空閑網路io線程去做解包工作的方法,核心是讓網路io線程epoll_wait時指定一個本地socket,我們通過這個socket去喚醒網路線程的epoll_wait 虛擬碼: 詳細說明 http://blog.csdn.net/analogous_love/article/details/53426777
定時器在伺服器編程中的應用 主要有兩種情境,一是定時發送心跳包。 另一個是流量控制,詳細說一下流量控制: 舉個例子,你去飯店吃飯,很多人都點了菜,飯店一般,給每個桌子都上點菜讓大家都先吃上,而不是先給一個桌子上好其他人等著
同理,當一個伺服器處理很多串連的時候,比如現在有三個串連A B C,一個背景工作執行緒,可能會這個背景工作執行緒一直在處理A的請求與應答,
那麼B C 是不是要一直等著,這個時候如何做呢,每次處理A的資料請求是記下A的位元組數,比如一次recv記下a1第二次a2 
a1 + a2 +... +an >= LIMIT
當A的資料已經超過LIMIT了,這個時候即使A有新資料我也不去收取了,騰下時間給B和C,B 和 C也一樣
給A,B,C分別設定一個定時器Ta,Tb,Tc,比如1秒後將Ta將A的LIMIT限制取消,也就是將A流量清0,這樣又能繼續處理A了。
這就是流量控制的一個方法,好處是避免某些人餓死,和飯店上菜一個道理
所以 定時器 也是網路編程的一個重要方面

流量控制可以搞一個伺服器優先處理策略
所有的定時器按優先順序順序排好
判斷第一個定時器的時間到了沒有,如果到了清空對應串連的流量,沒到就不用判斷了,接著判斷第二個,以此類推
儲存定時器可以用stl的優先隊列,讓它根據優先順序來排序,
這個會自動排序,小的排在前面,大的排在後面
有些搶票軟體的伺服器就有優先處理策略,充了錢的VIP伺服器優先處理你的請求

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.