網絡編程的基本概念


網絡編程是編寫服務器程序不可或缺的部分。 高性能的服務器程序一定都會有好的網絡處理程序,下面就來談一談網絡編程的基本概念。

凡是網絡編程,幾乎都離不開socket。socket分為阻塞與非阻塞兩種。阻塞的socket在調用讀寫接口是,會一直阻塞到socket上有可讀數據,或者socket可以寫入數據。而非阻塞socket,則會立即返回,不管socket是否可以讀寫。舉個簡單的例子,你去咖啡店買咖啡,發現前面排了很多人,對於阻塞模型來說,就是你會排隊一直等待。非阻塞模型,就是你看到要排隊,你就走了去干別的事了。很明顯,對於服務器來說,阻塞模型是嚴重影響服務器性能的。大部分情況下,都會使用非阻塞的調用

對於,阻塞與非阻塞的socket,又可以引申出兩個概念,同步與異步。很多同學會混淆這兩種說法,其實還是有一些區別的。在客戶端編程時,當要訪問網絡資源,都會調用一些已經封裝好的接口。同步接口就是說,調用接口時會一直等到有結果才返回;異步接口則是立即返回,等待有數據時,通過設置的回調函數通知調用者結果。同步並不等於阻塞的socket,異步也並不等於非阻塞的socket。不管是同步接口還是異步接口,都可以通過阻塞或是非阻塞的socket來實現。同樣以買咖啡的例子來說明同步與異步的區別:同步就是你一直排隊等你買到咖啡為止,異步就是你發現排隊人很多先去干別的事了,等到前面沒人了服務員會叫你過去。就是這樣

對於linux來說,socket有這樣幾種使用方式:阻塞,非阻塞(I/O復用),信號觸發,異步

服務器程序,一般不會使用阻塞方式,信號觸發也用得不多。較常見的就是I/O復用(select, poll, epoll),異步i/o這兩種。我們繼續來聊聊i/o復用。

對於服務器來說,每個連接的客戶端都對應着一個socket,但是不代表一個客戶端占用一個端口,這點千萬要注意。服務器能處理多少客戶端,是由文件描述符的數量來說的,其實就是一個int類型的值。顯然這並不是瓶頸,起決定因素的往往是 內存,多線程/進程模型,以及事件處理方式。這里重點說說事件處理方式。服務器處理成千上萬的客戶端連接,說到底就是處理這些socket上的讀寫事件。那么如何高效的處理這么多的連接呢? 還是以咖啡店的例子來說,剛開始是一個服務員處理一個顧客的需求,但是顧客越來越多,不可能有那么多服務員。於是一個服務員開始處理多個顧客。顧客付完錢,就找桌子坐下來玩手機了,沒必要在那排隊干等着。等你的咖啡好了,服務員通知你去取就行了。如果把顧客看作客戶端,那么顧客使用的是異步接口。服務員當作服務器,使用的是I/O復用,即一個線程/進程處理好多個顧客的請求。於是又誕生了兩種高效的事件處理模式:reactor與proactor。這兩種模式的區別是什么,在書本看到的說法是,reactor關注的是I/O就緒事件,proactor關注的是I/O完成事件。到底是什么意思?其實大多數人接觸到的可能都是I/O復用,這就是典型的reactor模式,即需要應用程序自己調用socket的讀寫接口來處理數據。而proactor則是直接告訴應用程序,哪個socket上來了什么數據,你直接處理就行了。怎么樣,這么說明白了嗎?還不明白,那我們再用買咖啡的例子來打比方。在買完咖啡后,你在那玩手機。把咖啡比作是數據,取咖啡比作是一個讀寫過程,喝咖啡當作是處理數據過程。reactor模型是,服務員大聲喊,xxx咖啡好了,這時你就要自己去取咖啡(讀過程),然后再回來喝(處理過程),喝完了你得自己再送回去(寫過程)。而proactor則是,服務員直接把你的咖啡端到桌子上,你負責喝就行了。這樣就很明顯可以看出,proactor省略了應用程序的讀寫過程,一般來說proactor都要依賴於異步的I/O.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM