網路程式設計基礎知識
女主宣言
OpsDev團隊自從九月中旬開啟技術分享活動以來,受到了廣大技術愛好者的好評,收效顯著。第一期公開課由李鋼老師開講,內容為“應用程式設計基礎課”,分為5節課,本文為本期的第二節課,重點講解網路基礎程式設計,包括網路結構、TCP程式設計模型和IO模型。現整理成文分享出來供大家一起學習。
PS:豐富的一線技術、多元化的表現形式,盡在“HULK一線技術雜談”,點關注哦!
前言
本人從事linux下web程式設計多年,最近有幸給組內同學做培訓,希望能夠給大家介紹下自己這些年在應用程式設計方面的經驗,今天給大家介紹以下網路程式設計方面需要掌握的基礎知識。
1
網路分層模型
先看一張圖:
從左到右向,分別是:
OSI七層模型
TCP/IP四層模型
應用程式實現部分和核心實現部分
這裡要認識到的是,我們最常用TCP的網路處理部分,都是由核心來完成的。
2
TCP服務端和客戶端程式設計模型
TCP連線建立和斷開
TCP建立連線需要三次握手,而斷開連線需要四次揮手,如圖:
這張圖清晰的說明了連線的建立、資料傳送以及斷開連線時所對應的程式設計函式,另外還有相應的TCP狀態轉換。
服務端客戶端程式設計函式
由此可見,服務端程式設計用到的主要函式為:
socket:建立一個socket,返回的檔案描述符fd之後用於bind和listen
bind:繫結socket和ip+port
listen:呼叫後,服務端狀態變為LISTEN,可以接收網路連線
accept:函式在連線建立後返回一個connfd,對這個檔案描述符的讀寫就是在做網路接收和傳送
read:網路對端傳送來的資料會放到核心的接收緩衝區,read就是從這個緩衝區中讀取資料到應用程式
write:應用程式要傳送資料到網路對端時,呼叫此函式,會現將資料寫到核心的傳送緩衝區中,之後核心會負責將資料傳送給網路對端
close:關閉連線
關於服務端的用於連線的fd和用於讀寫的fd,請見下圖:
客戶端程式設計用到的函式為:
socket:建立一個socket,之後用於連線伺服器,做資料讀寫用
connect:發起到服務端的連結,返回時TCP三次握手完成
write:同服務端的write
read:同服務端的read
close:關閉連線
幾個概念
backlog
核心中會維護兩個佇列:
未完成連線的佇列: 服務端收到客戶端的連線請求(SYNC),在三次握手完成前,會放到這個佇列中
完成連線的佇列:完成三次握手後就建立了一個TCP連線,這個連線會放到這個佇列中
linux的man listen中說:
The backlog argument defines the maximum length to which the queue of pending connections for sockfd may grow
我理解,backlog定義了未完成連線的佇列的最大長度
RTT
這個概念常常聽到,請見圖:
RTT的定義是Round-Trip Time,即資料包的往返時延
TCP Stream
我們通常說TCP是流式的,這是什麼樣的概念呢?
對應一個TCP連線,核心會給這個連線分配一個傳送緩衝和接收緩衝,我們的應用程式對這來兩個緩衝區的讀寫就是在做網路資料的接收和傳送。
而資料在網路上的傳輸是核心自己在維護的,當傳送緩衝區中有資料後,核心就把這些資料傳送給對端;同樣的,當對端有資料過來時,核心會把它放到接收緩衝區中,等待應用程式的讀寫。
這樣的傳送和接收資料的過程,就像水流一樣,所以我們說TCP是流式的。
TCP狀態轉換
TCP定義了很多狀態,這些狀態之間的轉換關係如下圖:
這些狀態都記住有難度,需要時查下就好了。
3
IO模型
網路操作就是IO操作,而且網路的IO是最慢的一種了,網路程式設計的很大難點就是妥善的處理好這一塊的問題。
Unix定義了多種IO操作模型,分別是:
阻塞IO
非阻塞IO
IO多路複用
訊號驅動IO
非同步IO
阻塞IO
這裡有一點非常重要的概念要先說明下,那就是阻塞的是什麼?
首先要記住:資料在網路上的傳輸完全是核心在控制的,應用程式中的read和write只是在讀寫接收緩衝和傳送緩衝。
讀阻塞:呼叫read時,如果接收緩衝區中沒有資料,那麼就會產生阻塞
寫阻塞:呼叫write時,如果傳送緩衝區中的資料沒有傳送出去,那麼就會產生阻塞
那麼如果沒有產生阻塞,那麼兩者的執行時間為:
read的執行時間為:將核心接收緩衝區的內容複製到使用者空間中的應用程式緩衝區
write的執行時間為:將使用者空間中的應用程式緩衝區的內容複製到核心的傳送緩衝區
非阻塞IO
理解了導致阻塞的原因,那麼非阻塞就非常好理解了:
當核心緩衝區無法讀寫時,read和write就會返回EWOULDBLOCK,應用程式就需要過會兒再來操作。
光是這樣,還不能實現高效能的網路程式,這是因為我們無法判斷應該什麼時間再來做讀寫操作。
如果一直迴圈讀寫,那麼CPU佔用會很居高不下;如果sleep一段時間,那麼多長時間合適呢?
所以,如果想開發高效能的網路程式,我們還需要別的武器。
IO多路複用
這是作業系統提供的一種通知機制,告訴應用程式何時可以做讀寫操作:
不同作業系統提供了不同的程式設計介面,一個非常有名的庫libevent就是對這些庫的一個統一介面封裝。
IO多路複用也是現在用的最多的一種高效能網路伺服器的IO處理模型,例如Nginx
訊號驅動IO
不同於IO多路複用,作業系統用訊號的方式告訴應用程式何時可以做讀寫操作:
非同步IO
最後這一種我沒有用過,從概念上理解,相當於作業系統將資料做完使用者空間和核心空間的複製後,才會通知應用程式:
4
面對如此眾多的伺服器
上面這些,都是筆者程式設計這些年,覺得非常受用的基礎知識。正確的認識這些知識,很多問題你都可以自己想明白了。
筆者也是在不斷學習中,如果有錯誤的地方,還望指正,我們共同進步,謝謝!
參考:
UNIX網路程式設計(卷1):
TCP/IP詳解(卷1):
Linux/UNIX系統程式設計手冊:
HULK一線技術雜談
由360雲平臺團隊打造的技術分享公眾號,內容涉及雲端計算、資料庫、大資料、監控、泛前端、自動化測試等眾多技術領域,透過夯實的技術積累和豐富的一線實戰經驗,為你帶來最有料的技術分享
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31555491/viewspace-2217522/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 程式設計基礎知識程式設計
- 計算機網路——基礎知識(一)計算機網路
- 網路安全基礎知識
- 《java程式設計基礎》java的基礎知識(三)Java程式設計
- Docker網路配置基礎知識Docker
- 網路協議基礎知識協議
- t-io網路程式設計基礎知識介紹程式設計
- Java併發程式設計——基礎知識(一)Java程式設計
- Java併發程式設計——基礎知識(二)Java程式設計
- 多執行緒程式設計基礎知識執行緒程式設計
- Java基礎——程式設計之路的開始,Java基礎知識Java程式設計
- 軟體設計師:程式設計語言基礎知識程式設計
- 大規模C++程式設計 -- 基礎知識C++程式設計
- 程式設計必備基礎 計算機組成原理+作業系統+計算機網路,計算機基礎——更適合程式設計師的程式設計必備基礎知識作業系統計算機網路程式設計師
- 程式基礎知識
- 談談網路協議 – 基礎知識協議
- WEB網路滲透的基礎知識Web
- 架構設計基礎知識整理架構
- 好程式設計師前端教程CSS基礎知識點程式設計師前端CSS
- 函數語言程式設計1-基礎知識函數程式設計
- 多執行緒程式設計的基礎知識點執行緒程式設計
- Linux下C語言程式設計基礎知識LinuxC語言程式設計
- 第七章——程式設計語言基礎知識程式設計
- NOI Linux 基礎知識與程式設計環境Linux程式設計
- 內網基礎知識內網
- 學習網路BGP必備基礎知識
- 網路營銷的基礎知識瞭解
- 卷積神經網路—基礎知識(1)卷積神經網路
- 遊戲基礎知識——“寵物”角色的設計遊戲
- 遊戲基礎知識——下位文明的設計遊戲
- 【計算機網路知識掃盲】10、DOS命令基礎(轉)計算機網路
- Java多執行緒程式設計基礎知識彙總Java執行緒程式設計
- 好程式設計師web前端教程分享JS基礎知識程式設計師Web前端JS
- Linux下C語言程式設計基礎知識(轉)LinuxC語言程式設計
- 網路安全基礎知識入門!網路安全學習教程
- 網路程式設計基礎-socket基礎程式設計
- [基礎入門]網路安全知識問答(二)!
- 學 Java 網路爬蟲,需要哪些基礎知識?Java爬蟲