日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深入学习理解UNIX网络编程

發布時間:2024/8/1 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入学习理解UNIX网络编程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

深入學習理解UNIX網絡編程

  • 一、OSI模型
  • 二、傳輸層協議
  • 三、傳輸控制協議(TCP)
  • 四、TCP連接的建立和終止
    • 1. 三路握手
    • 2. TCP選項
    • 3. TCP連接終止(4次揮手)
    • 4. TCP狀態轉換圖
    • 5. 觀察分組
  • 五、TIME_WAIT 狀態
  • 六、端口號
  • 七、TCP端口號與并發服務器
  • 八、緩沖區大小及限制
  • 九、套接字地址結構
    • 1. IPv4套接字地址結構
    • 2. 通用套接字地址結構
    • 3. 套接字地址結構的比較
  • 十、socket函數
  • 十一、connect函數
  • 十二、bind函數
  • 十三、listen函數
  • 十四、accept函數
  • 十五、fork和exec函數
  • 十六、并發服務器
  • 十七、close函數
  • 十八、I/O模型
    • 1. 阻塞式I/O模型
    • 2. 非阻塞式I/O模型
    • 3. I/O復用模型
    • 4. 信號驅動式I/O模型
    • 5. 異步I/O模型
    • 6. 各種I/O模型的比較
  • 十九、select函數
  • 二十、poll 函數

一、OSI模型

  • OSI(open systems interconnection):開放系統互連模型
  • 七層模型:
    • 1,2層:設備驅動程序和網絡硬件
    • 網絡層
    • 傳輸層:TCP和UDP(原始套接字:網絡應用可以繞過傳輸層直接使用網絡層的IP協議)
    • 5,6,7:應用層(Web客戶瀏覽器、Telnet客戶、Web服務器、FTP服務器)
  • 套接字編程接口:從應用層進入傳輸層的接口
  • 接口在傳輸層的原因:分別處理應用細節和通信細節、分隔用戶進程和操作系統內核
    • 應用層(頂上三層):
      • 處理具體網絡應用(FTP、Telnet、HTTP)的所有細節,卻對通信細節了解很少
      • 構成用戶進程
    • 底下四層:
      • 對具體網絡應用了解很少,卻處理所有通信細節(發送數據、等待確認、數據排序、計算驗證校驗和等等)
      • 作為操作系統內核的一部分

二、傳輸層協議

  • 傳輸層:TCP、UDP、SCTP(Stream Control Transmission Proto:流控制傳輸協議)
  • UDP:簡單的、不可靠的、無連接、數據報協議
    TCP:復雜的、可靠的、有連接、字節流協議(無消息邊界、流量控制、全雙工)
  • SCTP:可靠的、提供消息邊界、傳輸級別多宿支持

三、傳輸控制協議(TCP)

  • 有連接:TCP提供客戶與服務器之間的連接,通過連接交換數據
  • 可靠性:TCP向另一端發送數據時,要求對端返回一個確認,若沒有收到確認,TCP就自動重傳數據并等待更長的時間,數次重傳失敗后,TCP才放棄(4~10分鐘)
  • 往返時間(RTT:round-trip time):客戶與服務器之間數據傳輸的往返時間(TCP通過動態估算RTT來確定等待一個確認的時間)
  • 排序:給每字節關聯一個序列號(可以判斷數據是否重復傳遞)
  • 流量控制:TCP一次能夠從另一端接收多少字節(通告窗口)
  • 通告窗口(通告形式告知滑動窗口大小):指出接收緩存區中當前可用的空間量
  • 全雙工(full-duplex):在TCP連接的進出兩個方向可以既發送數據又接收數據

四、TCP連接的建立和終止

1. 三路握手

  • 被動打開:服務器必須準備好接受外來的連接(通過調用socket、bind函數)
  • 主動打開:客戶端通過調用connect函數發起主動打開,導致客戶端發送一個SYN(同步)分節,包含服務器將發送數據的初始序列號
  • 服務器確認客戶的SYN并發送ACK(確認),同時自己發送一個SYN分節(服務器將在連接中發送數據的初始序列號)
  • 客戶確認服務器的SYN

2. TCP選項

  • 每一個SYN可以含有多個TCP選項
  • TCP選項:
    • MSS(maximun segment size):最大分節大小
    • 窗口規模:告知對端的最大窗口大小(65535)
    • 時間戳:防止失而復現的分組可能造成的數據損壞

3. TCP連接終止(4次揮手)

  • 主動關閉:某個應用程序先調用close函數,發送一個FIN分節,表示數據發送完畢
  • 被動關閉:接收到FIN的對端,將FIN作為一個文件結束符傳遞給自己的應用進程,并確認FIN
  • 一段時間后,接收到這個文件結束符的應用進程調用close關閉socket,導致TCP發送一個FIN
  • 接收到最終FIN的原發送端確認這個FIN,發送ACK

4. TCP狀態轉換圖

5. 觀察分組

五、TIME_WAIT 狀態

  • TIME_WAIT狀態:執行主動關閉的一端
  • 持續時間(2MSL):最大分節生命期(MSL)的兩倍,一般
  • 分組在網絡中迷途:路由異常
    • 發生原因:
      • 某個路由器崩潰
      • 某兩個路由器之間的某個鏈路斷開
    • 導致:TCP超時重傳該分組,迷途的分組最終也到達,導致重復分組
  • TIME_WAIT狀態存在理由:
    • 可靠地實現TCP全雙工連接的終止:服務器沒有收到最終的ACK會再次發生FIN,TIME_WAIT狀態允許客戶端重新發送最終ACK
    • 允許老的重復分節在網絡中消逝:TIME_WAIT狀態持續2MSL,使老的重復分組最多存活MSL秒即被丟棄,保證建立新的TCP連接時,來自該連接先前化身(同一個IP和端口)的老的重復分組已經消逝

六、端口號

  • Port number:端口號(16位整數)
    • 眾所周知的端口:0~1023(例如:80分配給Web服務器)
    • 已登記的端口:1024~49151
    • 臨時端口:49152~65535(動態的、私有的)
  • 套接字對(socket pair):TCP連接兩端的四元組
    • 本地IP地址
    • 本地TCP端口號
    • 外地IP地址
    • 外地TCP端口號
  • 一個套接字:IP地址 + 端口號

七、TCP端口號與并發服務器

  • 服務器被動打開21端口,客戶使用記號 {:21,:*} 指出服務器的套接字對
  • 監聽套接字:“* . *”
  • 21端口存在3個套接字
    • 分節遞送給子進程1:來自206.168.112.219:1500,目的地為12.106.32.254:21
    • 分節遞送給子進程2:來自206.168.112.219:1501,目的地為12.106.32.254:21
    • 分節遞送給服務器主進程的監聽套接字:目的端口號為21的其他TCP連接

八、緩沖區大小及限制

  • MTU(maximun transmi unit):最大傳輸單元
  • 路徑MTU:兩個主機之間的路徑最小的MTU
  • IPv4數據報的最大大小是65535字節,最小鏈路MTU68字節
  • 以太網MTU:1500字節
  • 分片:IP數據報的大小超過相應鏈路的MTU
    • 主機和路由器都會分片
    • 若設置了IP數據報首部的“不分片”位(DF位),即不允許被分片,若超過大小,則導致ICMP出錯消息
    • 可利用DF位發現路徑MTU
  • 最小重組緩沖區大小:IPv4的最小數據報大小(576字節)
  • MSS:TCP最大分節大小
    • 重組緩沖區大小的實際值,避免分片(超過MTU將分片,MSS始終小于MTU)
    • 經常設置成MTU減去IP和TCP首部的固定長度(1500-20-20=1460字節)
  • TCP輸出:
    • 某個應用進程調用write:操作系統內核從應用進程的緩沖區中復制所有數據到套接字的發送緩沖區中
    • 可通過SO_SNDBUF(套接字選項)更改TCP套接字發送緩沖區大小
    • 若發送緩沖區無法容納數據:應用進程將被置于休眠狀態,內核將不從write系統調用返回,直到所有數據都復制到發送緩沖區中
    • TCP提取套接字發送緩沖區中的數據,并把它發送給對端TCP
    • 對端TCP必須確認(ACK)收到的數據,本端TCP才能從發送緩沖區中丟棄已確認的數據

九、套接字地址結構

1. IPv4套接字地址結構

  • IPv4套接字地址結構:網際套接字地址結構,以sockaddr_in命名
  • 說明:地址結構大小至少16字節
    • sin_len:長度字段
    • sin_family、sin_addr、sin_port:POSIX規范需要的三個字段
    • IP地址和端口號在套接字地址結構中以網絡字節序來存儲
    • 結構本身不在主機之間傳遞

2. 通用套接字地址結構

  • 套接字函數:以指向某個通用套接字地址結構的一個指針作為參數之一
  • 通用套接字地址結構的用途:對指向特定于協議的套接字地址結構的指針執行類型強制轉換

3. 套接字地址結構的比較

  • IPv4和Ipv6的套接字地址結構長度是固定的
  • 長度是可變時,當把指向某個套接字地址結構的指針作為一個參數傳遞給某個套接字函數時,會把該結構的長度作為另一個參數傳遞給這個函數

十、socket函數

  • 調用socket函數,指定期望的通信協議類型
    • family:協議族(常值)
    • type:套接字類型(常值)
    • protocol:某個協議類型常值或為0
    • 成功時返回:小的非負整數(套接字描述符:sockfd)
  • AF_XXX和PF_XXX對比:address family、protocol family(AF_:地址族、PF_:協議族)

十一、connect函數

  • TCP客戶用 connect 函數建立與TCP服務器的連接:
    • sockfd:socket函數返回的套接字描述符
    • 第二、三個參數:指向套接字地址結構的指針、該結構的大小
  • 調用connect函數將激發TCP的三路握手過程,連接建立成功或出錯時返回:
    • 出錯返回:
      • ETIMEDOUT:TCP客戶未收到SYN分節的響應(多次發送后,未收到)
      • ECONNREFUSED(硬錯誤):服務器對客戶SYN的響應是RST(復位),服務器主機在指定端口上沒有進程等待連接
      • ICMP錯誤(軟錯誤):客戶發出的SYN在中間的某個路由器引發了目的對不可達的ICMP錯誤
    • 套接字從CLOSED狀態轉移到SYN_SENT狀態
      • 成功:轉移為ESTABLISHED狀態
      • 失敗:該套接字不可用,必須關閉并重新調用socket

十二、bind函數

  • bind函數把一個本地協議地址賦予一個套接字:
    • sockfd:socket函數返回的套接字描述符
    • 第二、三個參數:指向特定于協議的地址結構的指針、該結構的長度
    • 返回錯誤:EADDRINUSE(地址已使用)
  • 進程可以把一個特定的IP地址捆綁到它的套接字上
    • TCP客戶:為在該套接字上發送的IP數據報指派了源IP地址
    • TCP服務器:限定該套接字只接收那些目的地為這個IP地址的客戶連接

十三、listen函數

  • listen函數由TCP服務器調用,在調用socket和bind函數之后,調用accept函數之前
  • listen函數把一個未連接的套接字轉換成一個被動套接字(被動打開),指示內核應接受指向該套接字的連接請求(套接字從CLOSED狀態轉換到LISTEN狀態)
  • 第二個參數(backlog):規定了內核應該為相應套接字排隊的最大連接個數
  • 內核為監聽套接字維護了兩個隊列:
    • 未完成連接隊列:服務器正在等待完成TCP三路握手過程,套接字處于SYN_RCVD狀態
      • 當客戶的SYN到達時,TCP在未完成連接隊列中創建一個新項
      • 響應三路握手的第二個分節(服務器的SYN響應和對客戶SYN的ACK),該新項一直保留到客戶的ACK到達前,或該項超時
    • 已完成連接隊列:已完成三路握手過程,套接字處于ESTABLISHED狀態
      • 該項從未完成連接隊列移到已完成連接隊列的隊尾

  • backlog參數:
    • backlog曾經規定了兩個隊列總和的最大值
    • Berkeley實現給backlog增設一個模糊因子(該因子乘以1.5得倒未處理隊列最大長度)
    • 不要把backlog定義為0,(不同實現有不同解釋)
    • 設定一個默認值,并允許通過命令行選項或環境變量覆蓋這個默認值

十四、accept函數

  • accept函數由TCP服務器調用,用于已完成連接隊列隊頭返回下一個已完成連接,若隊列為空,則進程被置于休眠狀態
  • 參數:
    • sockfd:監聽套接字描述符(由socket創建,隨后用作bind和listen的第一個參數的描述符)
    • cliaddr和addrlen(值-結果參數)用來返回已連接的客戶協議地址
  • accept返回值
    • 成功:
      • 由內核自動生成的一個全新描述符(已連接套接字描述符),代表與所返回客戶的TCP連接
      • 客戶進程的協議地址(cliaddr)以及該地址的大小(addrlen)(可將兩個設置為空指針,不返回協議地址)
    • 失敗:出錯指示的整數

十五、fork和exec函數

  • fork(派生)函數:
    • 調用一次,返回兩次:
      • 調用進程(父進程)中,返回新派生進程(子進程)的進程ID號
      • 子進程中返回0
        • 子進程只有一個父進程,父進程可以有很多子進程
        • 通過子進程調用getppid可以獲得父進程ID
        • 無法通過父進程獲得子進程ID
      • 調用accept后調用fork:已連接套接字在父進程和子進程之間共享
      • 用法:
        • 一個進程創建自身的副本(子進程):每個副本可以在另一個副本執行其他任務的同時處理各自的操作(網絡服務器)
        • 一個進程想要執行另一個程序:進程創建自身的副本后,其中一個副本調用exec把自身替換成新的程序(shell程序)
  • exec函數(6個):把當前進程映像(副本)替換成新的程序(進程ID不變)
    • 調用進程:調用exec的進程
    • 新程序:新執行的程序

十六、并發服務器

  • 并發服務器:同時服務多個客戶
  • 編寫方法:fork一個子進程來服務客戶(通過已連接套接字描述符:connfd),父進程等待新客戶連接(通過監聽套接字描述符:listenfd)
  • 父進程對connfd調用close后,不會終止服務器與客戶的連接(引用計數:2變為1,不等于0)

十七、close函數

  • 關閉套接字,終止TCP連接,調用后發送一個FIN
  • 并發服務器中:父進程close導致相應描述符的引用計數值減一,直到子進程close將計數值減為零時,才斷開TCP連接

十八、I/O模型

  • I/O復用:
    • 進程預先告知內核的能力(使內核一旦發現進程指定的一個或多個I/O條件就緒,就通知進程)
    • 由select和poll兩個函數支持
  • I/O復用使用場景:
    • 客戶處理多個描述符(交互式輸入和網絡套接字)
    • 一個客戶同時處理多個套接字
    • 一個TCP服務器既處理監聽套接字,又處理已連接套接字
    • 一個服務器既處理TCP,又處理UDP
    • 一個服務器處理多個服務或多個協議
  • I/O模型
    • 五種IO模型:阻塞式IO、非阻塞式IO、IO復用(select和poll)、信號驅動式IO、異步IO
    • 一個輸入操作包括兩個階段:
      • 等待數據準備好(等待數據從網絡中到達)
      • 從內核向進程復制數據(把數據從內核緩沖區復制到應用進程緩沖區)

1. 阻塞式I/O模型

  • BIO:Blocking I/O(阻塞IO)
  • 進程在從調用recvfrom(系統調用)開始到返回的整段時間內是被阻塞的

2. 非阻塞式I/O模型

  • 進程把一個套接字設置成非阻塞,是在通知內核:當所請求的I/O操作非得把本進程置于休眠狀態才能完成時,拒絕把進程置于休眠,而是返回一個錯誤
  • 通過輪詢(poll)內核,循環調用recvfrom來完成非阻塞IO(耗費大量CPU時間)

3. I/O復用模型

  • 可以調用select或poll,阻塞在這兩個系統調用中的某一個上,而不是阻塞在真正的I/O系統調用上
  • 阻塞于select調用,等待數據報套接字變為可讀(select返回套接字可讀時,再調用recvfrom復制數據)

4. 信號驅動式I/O模型

  • 使用信號,讓內核在描述符就緒時,發送SIGIO信號通知
  • 需要先開啟套接字的信號驅動式I/O功能,再通過sigaction系統調用安裝一個信號處理函數(調用將立即返回),進程此時繼續執行(非阻塞)

5. 異步I/O模型

  • AIO(asynchronous IO):告知內核啟動某個操作,并讓內核在整個操作完成后通知我們
  • 調用aio_read函數,告訴內核當整個操作完成時如何通知我們,該系統調用立即返回,且在等待IO完成期間,進程不被阻塞(下圖:要求內核完成操作時產生某個信號)

6. 各種I/O模型的比較

  • 前四種模型主要區別在第一階段,第二階段都是一樣的(數據從內核復制到調用者的緩沖區期間,進程阻塞于recvfrom調用:同步I/O)
  • 同步IO(前四種IO):導致請求進程阻塞,直到I/O操作完成
  • 異步IO:請求進程不會被阻塞

十九、select函數

  • 允許進程指示內核等待多個事件中的任何一個發生,并只在有一個或多個事件發生或經歷一段指定的時間后才喚醒它
  • 例:調用select告知內核對哪些描述符的哪些事件感興趣以及等待多長時間
    • {1,4,5}中的任何描述符準備好讀
    • {2,7}中的任何描述符準備好寫
    • {1,4}中的任何描述符有異常條件待處理
    • 經歷10.2秒
  • 參數:
    • timeout:告知內核等待所指定描述符中的任何一個就緒可花多長時間
      • 永遠等待下去:設置為空指針
      • 等待一段固定時間:設置秒數和微秒數
      • 根本不等待(輪詢:poll):檢查后立即返回,設置為0
    • 中間三個參數readset、writeset、exceptset:指定要讓內核測試讀、寫和異常條件的描述符(使用描述符集fd_set,整數數組)
    • maxfdp1:指定待測試的描述符的個數(最大描述符+1:即 0,1,2,…,maxfdp1-1)
  • 描述符就緒條件:
    • 套接字準備好讀:讀操作不會阻塞
      • 該套接字接收緩沖區中的數據字節數大于等于套接字接收緩沖區低水位標記的當前大小
      • 該連接的讀半部關閉(接收了FIN的TCP連接)
      • 該套接字是一個監聽套接字且已完成的連接數不為0
      • 其上有一個套接字錯誤待處理,讀操作返回錯誤(待處理錯誤)
    • 套接字準備好寫:
      • 該套接字發送緩沖區中的可用空間字節數大于等于套接字發送緩沖區低水位標記的當前大小
      • 該連接的寫半部關閉
      • 使用非阻塞式connect的套接字已建立連接(或者connect失敗了)
      • 其上有一個套接字錯誤待處理
    • 套接字有異常條件待處理:該套接字存在帶外數據或者仍處于帶外標記
  • 低水位標記設置為64:至少存在64字節的數據,否則應用進程不工作(防止少于64字節的數據準備好讀時select喚醒進程)
  • select的最大描述符數

二十、poll 函數

  • 與select類似,不過在處理流設備時,能夠提供額外的信息
  • poll識別三類數據:流的實現
    • 普通:所有正規TCP數據和UDP數據、讀半部關閉時、監聽套接字上有新的連接可用
    • 優先級帶:TCP的帶外數據
    • 高優先級
  • 參數:
    • fdarray:指向一個結構數組第一個元素的指針(每個數組元素都是一個pollfd結構:用于指定測試某個給定描述符fd的條件)
      • evenets:測試條件
      • revents:返回該描述符的狀態
    • nfds:結構數組中元素的個數
    • timeout:指定poll函數返回前等待多長時間
      • INFTIM(負值):永遠等待
      • 0:立即返回,不阻塞進程
      • 大于0:等待指定數目的毫秒數
  • 返回:
    • 就緒描述符的個數(revents成員值非0的描述符個數)
    • 0:定時器到時之前沒有任何描述符就緒
    • -1:發生錯誤

總結

以上是生活随笔為你收集整理的深入学习理解UNIX网络编程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。