1. 程式人生 > >《TCP/IP高效程式設計》 ---------閱讀筆記

《TCP/IP高效程式設計》 ---------閱讀筆記

技巧1:理解面向連線與無連線協議之間的區別

對於無連線來說,每個分組的處理都獨立於所有其他分組,而對於面向連線的協議來說,協議實現則維護了與後續分組有關的狀態資訊。

RTO定時器超時並不意味著原來的資料沒有到達目的地,有可能是ACK丟失,或者原來的段在網路中延遲的時間太長,以至於其在ACK到達之前的RTO超時了,但這並不會造成什麼問題,因為如果原來的資料確實到達了,那麼重傳的資料會處於接收端TCP接收視窗範圍之外,會被丟棄。

技巧2TCP是一種流協議

資料是以位元組流的形式傳遞給接收者的,沒有固定的報文或者報文邊界概念,從這方面來說,讀取TCP資料無法預先得知再一次指定的讀呼叫中會返回多少位元組。儘管資料是以IP分組的形式傳輸的,但分組中的資料量與send呼叫中傳送給TCP多少資料並沒有直接關係,而且,接受程式沒有什麼可靠的方法可以判斷資料是如何分組的,因為在兩次recv呼叫之間可能會有多個分組到來。TCP會記錄它傳送了多少位元組,但是不會記錄這些位元組是如何分組的。

技巧3TCP/IP不是輪詢的

tcp無法將連線的丟失立即通知給應用程式,我們研究為什麼TCP不提供這種通知機制,不這麼做的優點和缺點,以及應用程式必須完成哪些工作以檢測連線的丟失。

為什麼不輪詢,因為輪詢都會消耗淨荷的網路支援,並且大部分應用程式都不需要即時通知,因此不併為之付出頻寬的代價。

keep-alive(保持活躍)用來檢測死連結,應用程式啟動保持活躍機制時,TCP會在連線空閒一段時間之後,向對等實體傳送一個特殊的段,如果對等主機可達,且對等程式仍在執行,對等實體會以ACK形式相應,在這種情況下,TCP活躍機制將空閒時間重置為0。如果對等主機可達但是應用程式沒有執行,則對等實體的TCP會以RST響應,TCP傳送的保持活躍訊號會丟棄連線並相應應用程式返回一個錯誤。如果對等主機沒有以ACK或RST響應,TCP傳送的保持活躍會繼續傳送保持活躍探測訊號,直到它認為對等實體不可達或者崩潰為止。

技巧4:理解TCP的寫操作

使用者程式對一條TCP連線進行寫呼叫時,首先會將資料從使用者快取區複製到核心中去,從此之後,可能發生的情況就與連線的狀態有關了,TCP可能傳送全部、部分或者不發資料。總的來說,除非TCP快取區滿了,否則寫操作是不會被阻塞的,也就是說,寫操作基本總是能立即返回的,但他們返回時並不能保證對所寫的資料進行了哪些處理。

技巧5:理解TCP的有序釋放操作

shutdown呼叫 :shutdown(int s, inthow)其中how0,1,2分別表示關閉接受,傳送,兩端。關閉套接字和shutdown之間是有很大的區別的,即使將how值設為2來使用,實際上也沒有“關閉“套接字,也就是說,並沒有釋放套接字及其資源。同時,呼叫shutdown時,會影響到所有打開了那個套接字的程序。

當我們伺服器崩潰之後,試圖重啟時,會收到錯誤的提示“Address already in use“,過了幾分鐘後才能重啟伺服器。

因為這時候主動停止的那一端還處於TIME-WAIT狀態,並在此狀態停留 了2MSL,通過設定套接字選項SO_REUSEADDR,指示TCP允許我們繫結到一個已經在使用的埠上去。

技巧7:如何使connect呼叫超時

   通常在套接字阻塞的情況下,在收到對客戶端SYN的ACK之前,connect是不會返回的,如果網路阻塞,或者要連線的主機還沒有啟動,所需要時間可能更長,因此允許放棄connect通常是一項很有用的功能,當然TCP最終會放棄connect呼叫,但是預設時間(75秒)可能比我們希望等待的時間要長。

有兩種方法,其一在connect前使用alarm(inttime)告警,表示希望等待的時間不超過time秒。

其二,在connect之前使用select,在select中設定時間超時。

技巧8:避免資料複製

其一,如果知道要在讀取到緩衝區的資料的前面加上一個首部,在讀取時就應該為其留有空間。

其二,將報文分組定義為一個結構,這個結構將資料緩衝區作為它的一個元素,然後只要將資料讀入適當的結構欄位中去就可以了。

其三,使用合併寫操作。

使用共享記憶體幾乎可以避免所有的資料複製,包括程序間的。

技巧9:使用前將結構sockaddr_in清零

儘管通常我們只是用sockaddr_in結構的三個欄位,sin_family,sin_port和sin_addr,但在大多數實現中它還包含其他部分,因此必須在使用錢,將整個地址結構清零就成了一種慣用的做法。