日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

深入学习理解UNIX网络编程

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

深入學習理解UNIX網(wǎng)絡編程

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

一、OSI模型

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

二、傳輸層協(xié)議

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

三、傳輸控制協(xié)議(TCP)

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

四、TCP連接的建立和終止

1. 三路握手

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

2. TCP選項

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

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

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

4. TCP狀態(tài)轉換圖

5. 觀察分組

五、TIME_WAIT 狀態(tài)

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

六、端口號

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

七、TCP端口號與并發(fā)服務器

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

八、緩沖區(qū)大小及限制

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

九、套接字地址結構

1. IPv4套接字地址結構

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

2. 通用套接字地址結構

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

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

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

十、socket函數(shù)

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

十一、connect函數(shù)

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

十二、bind函數(shù)

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

十三、listen函數(shù)

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

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

十四、accept函數(shù)

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

十五、fork和exec函數(shù)

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

十六、并發(fā)服務器

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

十七、close函數(shù)

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

十八、I/O模型

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

1. 阻塞式I/O模型

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

2. 非阻塞式I/O模型

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

3. I/O復用模型

  • 可以調用select或poll,阻塞在這兩個系統(tǒng)調用中的某一個上,而不是阻塞在真正的I/O系統(tǒng)調用上
  • 阻塞于select調用,等待數(shù)據(jù)報套接字變?yōu)榭勺x(select返回套接字可讀時,再調用recvfrom復制數(shù)據(jù))

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

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

5. 異步I/O模型

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

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

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

十九、select函數(shù)

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

二十、poll 函數(shù)

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

總結

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

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