當前位置:首頁 » 操作系統 » linux內核tcp

linux內核tcp

發布時間: 2022-08-02 02:30:00

1. 請問 Tcp/Ip協議在linux內核中架構模式 是什麼樣子的 回答的好的再補充分數。

這個問題問的好啊,我也有類似的問題。目前自己的答案是TCP/IP的每一層在linux內核中都是由不同的函數和數據結構組成的,不過目前我還沒有整理出來。

2. linux下怎麼設置tcp

Socket的send函數在執行時報EAGAIN的錯誤 當客戶通過Socket提供的send函數發送大的數據包時,就可能返回一個EGGAIN的錯誤。該錯誤產生的原因是由於send 函數中的size變數大小超過了tcp_sendspace的值。tcp_sendspace定義了應用在調用send之前能夠在kernel中緩存的數據量。當應用程序在socket中設置了O_NDELAY或者O_NONBLOCK屬性後,如果發送緩存被占滿,send就會返回EAGAIN的錯誤。 為了消除該錯誤,有三種方法可以選擇: 1.調大tcp_sendspace,使之大於send中的size參數 ---no -p -o tcp_sendspace=65536 2.在調用send前,在setsockopt函數中為SNDBUF設置更大的值 3.使用write替代send,因為write沒有設置O_NDELAY或者O_NONBLOCK 1. tcp 收發緩沖區默認值 [root@qljt core]# cat /proc/sys/net/ipv4/tcp_rmem 4096 87380 4161536 87380 :tcp接收緩沖區的默認值 [root@qljt core]# cat /proc/sys/net/ipv4/tcp_wmem 4096 16384 4161536 16384 : tcp 發送緩沖區的默認值 2. tcp 或udp收發緩沖區最大值 [root@qljt core]# cat /proc/sys/net/core/rmem_max 131071 131071:tcp 或 udp 接收緩沖區最大可設置值的一半。 也就是說調用 setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen); 時rcv_size 如果超過 131071,那麼 getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen); 去到的值就等於 131071 * 2 = 262142 [root@qljt core]# cat /proc/sys/net/core/wmem_max 131071 131071:tcp 或 udp 發送緩沖區最大可設置值得一半。 跟上面同一個道理 3. udp收發緩沖區默認值 [root@qljt core]# cat /proc/sys/net/core/rmem_default 111616:udp接收緩沖區的默認值 [root@qljt core]# cat /proc/sys/net/core/wmem_default 111616 111616:udp發送緩沖區的默認值 . tcp 或udp收發緩沖區最小值 tcp 或udp接收緩沖區的最小值為 256 bytes,由內核的宏決定; tcp 或udp發送緩沖區的最小值為 2048 bytes,由內核的宏決定 setsockopt設置socket狀態 1.closesocket(一般不會立即關閉而經歷TIME_WAIT的過程)後想繼續重用該socket: BOOL bReuseaddr=TRUE; setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL)); 2. 如果要已經處於連接狀態的soket在調用closesocket後強制關閉,不經歷TIME_WAIT的過程: BOOL bDontLinger = FALSE; setsockopt(s,SOL_SOCKET,SO_DONTLINGER,(const char*)&bDontLinger,sizeof(BOOL)); 3.在send(),recv()過程中有時由於網路狀況等原因,發收不能預期進行,而設置收發時限: int nNetTimeout=1000;//1秒 //發送時限 setsockopt(socket,SOL_S0CKET,SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int)); //接收時限 setsockopt(socket,SOL_S0CKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int)); 4.在send()的時候,返回的是實際發送出去的位元組(同步)或發送到socket緩沖區的位元組(非同步);系統默認的狀態發送和接收一次為8688位元組(約為8.5K);在實際的過程中發送數據 和接收數據量比較大,可以設置socket緩沖區,而避免了send(),recv()不斷的循環收發: // 接收緩沖區 int nRecvBuf=32*1024;//設置為32K setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int)); //發送緩沖區 int nSendBuf=32*1024;//設置為32K setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int)); 5. 如果在發送數據的時,希望不經歷由系統緩沖區到socket緩沖區的拷貝而影響程序的性能: int nZero=0; setsockopt(socket,SOL_S0CKET,SO_SNDBUF,(char *)&nZero,sizeof(nZero)); 6.同上在recv()完成上述功能(默認情況是將socket緩沖區的內容拷貝到系統緩沖區): int nZero=0; setsockopt(socket,SOL_S0CKET,SO_RCVBUF,(char *)&nZero,sizeof(int)); 7.一般在發送UDP數據報的時候,希望該socket發送的數據具有廣播特性: BOOL bBroadcast=TRUE; setsockopt(s,SOL_SOCKET,SO_BROADCAST,(const char*)&bBroadcast,sizeof(BOOL)); 8.在client連接伺服器過程中,如果處於非阻塞模式下的socket在connect()的過程中可以設置connect()延時,直到accpet()被呼叫(本函數設置只有在非阻塞的過程中有顯著的 作用,在阻塞的函數調用中作用不大) BOOL bConditionalAccept=TRUE; setsockopt(s,SOL_SOCKET,SO_CONDITIONAL_ACCEPT,(const char*)&bConditionalAccept,sizeof(BOOL)); 9.如果在發送數據的過程中(send()沒有完成,還有數據沒發送)而調用了closesocket(),以前我們一般採取的措施是"從容關閉"shutdown(s,SD_BOTH),但是數據是肯定丟失了,如何設置讓程序滿足具體應用的要求(即讓沒發完的數據發送出去後在關閉socket)? struct linger { u_short l_onoff; u_short l_linger; }; linger m_sLinger; m_sLinger.l_onoff=1;//(在closesocket()調用,但是還有數據沒發送完畢的時候容許逗留) // 如果m_sLinger.l_onoff=0;則功能和2.)作用相同; m_sLinger.l_linger=5;//(容許逗留的時間為5秒) setsockopt(s,SOL_SOCKET,SO_LINGER,(const char*)&m_sLinger,sizeof(linger)); 設置套介面的選項。 #include <winsock.h> int PASCAL FAR setsockopt( SOCKET s, int level, int optname, const char FAR* optval, int optlen); s:標識一個套介面的描述字。 level:選項定義的層次;目前僅支持SOL_SOCKET和IPPROTO_TCP層次。 optname:需設置的選項。 optval:指針,指向存放選項值的緩沖區。 optlen:optval緩沖區的長度。 注釋: setsockopt()函數用於任意類型、任意狀態套介面的設置選項值。盡管在不同協議層上存在選項,但本函數僅定義了最高的「套介面」層次上的選項。選項影響套介面的操作,諸如加急數據是否在普通數據流中接收,廣播數據是否可以從套介面發送等等。 有兩種套介面的選項:一種是布爾型選項,允許或禁止一種特性;另一種是整形或結構選項。允許一個布爾型選項,則將optval指向非零整形數;禁止一個選項optval指向一個等於零的整形數。對於布爾型選項,optlen應等於sizeof(int);對其他選項,optval指向包含所需選項的整形數或結構,而optlen則為整形數或結構的長度。SO_LINGER選項用於控制下述情況的行動:套介面上有排隊的待發送數據,且 closesocket()調用已執行。參見closesocket()函數中關於SO_LINGER選項對closesocket()語義的影響。應用程序通過創建一個linger結構來設置相應的操作特性: struct linger { int l_onoff; int l_linger; }; 為了允許SO_LINGER,應用程序應將l_onoff設為非零,將l_linger設為零或需要的超時值(以秒為單位),然後調用setsockopt()。為了允許SO_DONTLINGER(亦即禁止SO_LINGER),l_onoff應設為零,然後調用setsockopt()。 預設條件下,一個套介面不能與一個已在使用中的本地地址捆綁(參見bind())。但有時會需要「重用」地址。因為每一個連接都由本地地址和遠端地址的組合唯一確定,所以只要遠端地址不同,兩個套介面與一個地址捆綁並無大礙。為了通知WINDOWS套介面實現不要因為一個地址已被一個套介面使用就不讓它與另一個套介面捆綁,應用程序可在bind()調用前先設置SO_REUSEADDR選項。請注意僅在bind()調用時該選項才被解釋;故此無需(但也無害)將一個不會共用地址的套介面設置該選項,或者在bind()對這個或其他套介面無影響情況下設置或清除這一選項。 一個應用程序可以通過打開SO_KEEPALIVE選項,使得WINDOWS套介面實現在TCP連接情況下允許使用「保持活動」包。一個WINDOWS套介面實現並不是必需支持「保持活動」,但是如果支持的話,具體的語義將與實現有關,應遵守RFC1122「Internet主機要求-通訊層」中第 4.2.3.6節的規范。如果有關連接由於「保持活動」而失效,則進行中的任何對該套介面的調用都將以WSAENETRESET錯誤返回,後續的任何調用將以WSAENOTCONN錯誤返回。 TCP_NODELAY選項禁止Nagle演算法。Nagle演算法通過將未確認的數據存入緩沖區直到蓄足一個包一起發送的方法,來減少主機發送的零碎小數據包的數目。但對於某些應用來說,這種演算法將降低系統性能。所以TCP_NODELAY可用來將此演算法關閉。應用程序編寫者只有在確切了解它的效果並確實需要的情況下,才設置TCP_NODELAY選項,因為設置後對網路性能有明顯的負面影響。TCP_NODELAY是唯一使用IPPROTO_TCP層的選項,其他所有選項都使用SOL_SOCKET層。 如果設置了SO_DEBUG選項,WINDOWS套介面供應商被鼓勵(但不是必需)提供輸出相應的調試信息。但產生調試信息的機制以及調試信息的形式已超出本規范的討論范圍。 setsockopt()支持下列選項。其中「類型」表明optval所指數據的類型。 選項 類型 意義 SO_BROADCAST BOOL 允許套介面傳送廣播信息。 SO_DEBUG BOOL 記錄調試信息。 SO_DONTLINER BOOL 不要因為數據未發送就阻塞關閉操作。設置本選項相當於將SO_LINGER的l_onoff元素置為零。 SO_DONTROUTE BOOL 禁止選徑;直接傳送。 SO_KEEPALIVE BOOL 發送「保持活動」包。 SO_LINGER struct linger FAR* 如關閉時有未發送數據,則逗留。 SO_OOBINLINE BOOL 在常規數據流中接收帶外數據。 SO_RCVBUF int 為接收確定緩沖區大小。 SO_REUSEADDR BOOL 允許套介面和一個已在使用中的地址捆綁(參見bind())。 SO_SNDBUF int 指定發送緩沖區大小。 TCP_NODELAY BOOL 禁止發送合並的Nagle演算法。 setsockopt()不支持的BSD選項有: 選項名 類型 意義 SO_ACCEPTCONN BOOL 套介面在監聽。 SO_ERROR int 獲取錯誤狀態並清除。 SO_RCVLOWAT int 接收低級水印。 SO_RCVTIMEO int 接收超時。 SO_SNDLOWAT int 發送低級水印。 SO_SNDTIMEO int 發送超時。 SO_TYPE int 套介面類型。 IP_OPTIONS 在IP頭中設置選項。 返回值: 若無錯誤發生,setsockopt()返回0。否則的話,返回SOCKET_ERROR錯誤,應用程序可通過WSAGetLastError()獲取相應錯誤代碼。 錯誤代碼: WSANOTINITIALISED:在使用此API之前應首先成功地調用WSAStartup()。 WSAENETDOWN:WINDOWS套介面實現檢測到網路子系統失效。 WSAEFAULT:optval不是進程地址空間中的一個有效部分。 WSAEINPROGRESS:一個阻塞的WINDOWS套介面調用正在運行中。 WSAEINVAL:level值非法,或optval中的信息非法。 WSAENETRESET:當SO_KEEPALIVE設置後連接超時。 WSAENOPROTOOPT:未知或不支持選項。其中,SOCK_STREAM類型的套介面不支持SO_BROADCAST選項,SOCK_DGRAM 類型的套介面不支持SO_DONTLINGER 、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE選項。 WSAENOTCONN:當設置SO_KEEPALIVE後連接被復位。 WSAENOTSOCK:描述字不是一個套介面。

3. Linux系統一般由哪4個部分組成

Linux系統一般有4個主要部分:內核、shell、文件系統和應用程序。內核、shell和文件系統一起形成了基本的操作系統結構,它們使得用戶可以運行程序、管理文件並使用系統。

一、Linux內核

內核是操作系統的核心,具有很多最基本功能,如虛擬內存、多任務、共享庫、需求載入、可執行程序和TCP/IP網路功能。Linux內核的模塊分為以下幾個部分:存儲管理、CPU和進程管理、文件系統、設備管理和驅動、網路通信、系統的初始化和系統調用等。

二、Linuxshell

shell是系統的用戶界面,提供了用戶與內核進行交互操作的一種介面。它接收用戶輸入的命令並把它送入內核去執行,是一個命令解釋器。另外,shell編程語言具有普通編程語言的很多特點,用這種編程語言編寫的shell程序與其他應用程序具有同樣的效果。

三、Linux文件系統

文件系統是文件存放在磁碟等存儲設備上的組織方法。Linux系統能支持多種目前流行的文件系統,如EXT2、EXT3、FAT、FAT32、VFAT和ISO9660。

四、Linux應用程序

標準的Linux系統一般都有一套都有稱為應用程序的程序集,它包括文本編輯器、編程語言、XWindow、辦公套件、Internet工具和資料庫等。

(3)linux內核tcp擴展閱讀:

LINUX系統的特點

1、Linux是一款免費的操作系統,用戶可以通過網路或其他途徑免費獲得,並可以任意修改其源代碼。這是其他的操作系統所做不到的。

2、在Linux下通過相應的模擬器運行常見的DOS、Windows的程序。這為用戶從Windows轉到Linux奠定了基礎。

3、Linux可以運行在多種硬體平台上,如具有x86、680x0、SPARC、Alpha等處理器的平台。此外Linux還是一種嵌入式操作系統,可以運行在掌上電腦、機頂盒或游戲機上。

4. 一般優化linux的內核,需要優化什麼參數

作為高性能WEB伺服器,只調整Nginx本身的參數是不行的,因為Nginx服務依賴於高性能的操作系統。

以下為常見的幾個Linux內核參數優化方法。

  • net.ipv4.tcp_max_tw_buckets

  • 對於tcp連接,服務端和客戶端通信完後狀態變為timewait,假如某台伺服器非常忙,連接數特別多的話,那麼這個timewait數量就會越來越大。
    畢竟它也是會佔用一定的資源,所以應該有一個最大值,當超過這個值,系統就會刪除最早的連接,這樣始終保持在一個數量級。
    這個數值就是由net.ipv4.tcp_max_tw_buckets這個參數來決定的。
    CentOS7系統,你可以使用sysctl -a |grep tw_buckets來查看它的值,默認為32768,
    你可以適當把它調低,比如調整到8000,畢竟這個狀態的連接太多也是會消耗資源的。
    但你不要把它調到幾十、幾百這樣,因為這種狀態的tcp連接也是有用的,
    如果同樣的客戶端再次和服務端通信,就不用再次建立新的連接了,用這個舊的通道,省時省力。

  • net.ipv4.tcp_tw_recycle = 1

  • 該參數的作用是快速回收timewait狀態的連接。上面雖然提到系統會自動刪除掉timewait狀態的連接,但如果把這樣的連接重新利用起來豈不是更好。
    所以該參數設置為1就可以讓timewait狀態的連接快速回收,它需要和下面的參數配合一起使用。

  • net.ipv4.tcp_tw_reuse = 1

  • 該參數設置為1,將timewait狀態的連接重新用於新的TCP連接,要結合上面的參數一起使用。

  • net.ipv4.tcp_syncookies = 1

  • tcp三次握手中,客戶端向服務端發起syn請求,服務端收到後,也會向客戶端發起syn請求同時連帶ack確認,
    假如客戶端發送請求後直接斷開和服務端的連接,不接收服務端發起的這個請求,服務端會重試多次,
    這個重試的過程會持續一段時間(通常高於30s),當這種狀態的連接數量非常大時,伺服器會消耗很大的資源,從而造成癱瘓,
    正常的連接進不來,這種惡意的半連接行為其實叫做syn flood攻擊。
    設置為1,是開啟SYN Cookies,開啟後可以避免發生上述的syn flood攻擊。
    開啟該參數後,服務端接收客戶端的ack後,再向客戶端發送ack+syn之前會要求client在短時間內回應一個序號,
    如果客戶端不能提供序號或者提供的序號不對則認為該客戶端不合法,於是不會發ack+syn給客戶端,更涉及不到重試。

  • net.ipv4.tcp_max_syn_backlog

  • 該參數定義系統能接受的最大半連接狀態的tcp連接數。客戶端向服務端發送了syn包,服務端收到後,會記錄一下,
    該參數決定最多能記錄幾個這樣的連接。在CentOS7,默認是256,當有syn flood攻擊時,這個數值太小則很容易導致伺服器癱瘓,
    實際上此時伺服器並沒有消耗太多資源(cpu、內存等),所以可以適當調大它,比如調整到30000。

  • net.ipv4.tcp_syn_retries

  • 該參數適用於客戶端,它定義發起syn的最大重試次數,默認為6,建議改為2。

  • net.ipv4.tcp_synack_retries

  • 該參數適用於服務端,它定義發起syn+ack的最大重試次數,默認為5,建議改為2,可以適當預防syn flood攻擊。

  • net.ipv4.ip_local_port_range

  • 該參數定義埠范圍,系統默認保留埠為1024及以下,以上部分為自定義埠。這個參數適用於客戶端,
    當客戶端和服務端建立連接時,比如說訪問服務端的80埠,客戶端隨機開啟了一個埠和服務端發起連接,
    這個參數定義隨機埠的范圍。默認為32768 61000,建議調整為1025 61000。

  • net.ipv4.tcp_fin_timeout

  • tcp連接的狀態中,客戶端上有一個是FIN-WAIT-2狀態,它是狀態變遷為timewait前一個狀態。
    該參數定義不屬於任何進程的該連接狀態的超時時間,默認值為60,建議調整為6。

  • net.ipv4.tcp_keepalive_time

  • tcp連接狀態里,有一個是established狀態,只有在這個狀態下,客戶端和服務端才能通信。正常情況下,當通信完畢,
    客戶端或服務端會告訴對方要關閉連接,此時狀態就會變為timewait,如果客戶端沒有告訴服務端,
    並且服務端也沒有告訴客戶端關閉的話(例如,客戶端那邊斷網了),此時需要該參數來判定。
    比如客戶端已經斷網了,但服務端上本次連接的狀態依然是established,服務端為了確認客戶端是否斷網,
    就需要每隔一段時間去發一個探測包去確認一下看看對方是否在線。這個時間就由該參數決定。它的默認值為7200秒,建議設置為30秒。

  • net.ipv4.tcp_keepalive_intvl

  • 該參數和上面的參數是一起的,服務端在規定時間內發起了探測,查看客戶端是否在線,如果客戶端並沒有確認,
    此時服務端還不能認定為對方不在線,而是要嘗試多次。該參數定義重新發送探測的時間,即第一次發現對方有問題後,過多久再次發起探測。
    默認值為75秒,可以改為3秒。

  • net.ipv4.tcp_keepalive_probes

  • 第10和第11個參數規定了何時發起探測和探測失敗後再過多久再發起探測,但並沒有定義一共探測幾次才算結束。
    該參數定義發起探測的包的數量。默認為9,建議設置2。
    設置和範例
    在Linux下調整內核參數,可以直接編輯配置文件/etc/sysctl.conf,然後執行sysctl -p命令生效

5. 怎麼檢測linux 內核 tcp發送緩沖區溢出

內核,是一個操作系統的核心。它負責管理系統的進程、內存、設備驅動程序、文件和網路系統,決定著系統的性能和穩定性。Linux作為一個自由軟體, 在廣大愛好者的支持下,內核版本不斷更新。新的內核修訂了舊內核的bug,並增加了許多新的特性。

6. Linux裡面tcp協議屬於四層服務嗎

TCP/IP 的分層管理
TCP/IP 協議按照層次分為 4 層:應用層、傳輸層、網路層、數據鏈路層。 對於分層這個概念,大家一定不陌生,比如我們的分布式架構體系中會分為業務層、服務層、基礎支撐層。比如docker,也是基於分層來實現。所以我們會發現,復雜的程序都需要分層,這個是軟體設計的要求,每一層專注於當前領域的事情。如果某些地方需要修改,我們只需要把變動的層替換掉就行,一方面改動影響較少,另一方面整個架構的靈活性也更高。 最後,在分層之後,整個架構的設計也變得相對簡單了。
分層負載

了解了分層的概念以後,我們再去理解所謂的二層負載、三層負載、四層負載、七層負載就容易多了。
一次 http 請求過來,一定會從應用層到傳輸層,完成整個交互。只要是在網路上跑的數據包,都是完整的。可以有下層沒上層,絕對不可能有上層沒下層。
二層負載

二層負載是針對 MAC,負載均衡伺服器對外依然提供一個 VIP(虛 IP),集群中不同的機器採用相同 IP 地址,但是機器的 MAC 地址不一樣。當負載均衡伺服器接受到請求之後,通過改寫報文的目標 MAC 地址的方式將請求轉發到目標機器實現負載均衡
二層負載均衡會通過一個虛擬 MAC 地址接收請求,然後再分配到真實的 MAC 地址
三層負載均衡

三層負載是針對 IP,和二層負載均衡類似,負載均衡伺服器對外依然提供一個 VIP(虛 IP),但是集群中不同的機器採用不同的 IP 地址。當負載均衡伺服器接受到請求之後,根據不同的負載均衡演算法,通過 IP 將請求轉發至不同的真實伺服器
三層負載均衡會通過一個虛擬 IP 地址接收請求,然後再分配到真實的 IP 地址
四層負載均衡

四層負載均衡工作在 OSI 模型的傳輸層,由於在傳輸層,只有 TCP/UDP 協議,這兩種協議中除了包含源 IP、目標 IP 以外,還包含源埠號及目的埠號。四層負載均衡伺服器在接受到客戶端請求後,以後通過修改數據包的地址信息(IP+埠號)將流量轉發到應用伺服器。
四層通過虛擬 IP + 埠接收請求,然後再分配到真實的伺服器
七層負載均衡

七層負載均衡工作在 OSI 模型的應用層,應用層協議較多,常用 http、radius、dns 等。七層負載就可以基於這些協議來負載。這些應用層協議中會包含很多有意義的內容。比如同一個Web 伺服器的負載均衡,除了根據 IP 加埠進行負載外,還可根據七層的 URL、瀏覽器類別來決定是否要進行負載均衡
比如:在nginx層做7層均衡,讓一個uid的請求盡量落到同一個機器上

7. linux 內核怎麼實現tcp nat 轉換的

1.兩個網路介面、一個內,一個外2.NAT轉換(內)操作步驟:1.設置Linux內核支持ip數據包的轉發:echo "1" > /proc/sys/net/ipv4/ip_forward2.載入實現NAT功能必要的內核模塊:modprobe ip_tablesmodprobe ip_nat_ftpmodprobe ip_nat_ircmodprobe...

8. linux內核中tcp分組是怎麼實現的

以前一直使用的網路通訊的函數都是工作在阻塞模式。在看connect實現源碼時,突然想到tcp/ip的
三次握手在內核如何實現的,尤其是在非阻塞模式下式,涉及到等待對端回送ack包,而本端又要立即返
回,想來這種實現肯定是遵循某種規則或是將所有的相關函數組合起來。
查看一些網路通信書籍,可知果然如此。應用編程如果設置為非阻塞模式,則連接時,connect發送
SYN包後立即返回-EINPROGRESS,表示操作正在處理中;隨後應用可以在connect返回後做一些其它的處理,
最後在select函數中來捕獲socket的連接、讀寫、異常事件以觸發相關操作,下面我們看看內核中的相關
實現:
一、tcp/ip連接的三次握手過程:
client SYN包---> server
client <---ACK包 server
client ACK包---> server
二、客戶端支持
client發送2個包,一個SYN包,一個對伺服器的響應ACK包。
client函數調用鏈:connect-->sys_connect->inet_stream_connect->tcp_connect...
看inet_stream_connect中實現的部分代碼段:
...
switch (sock->state) {
...
/*此處調用tcp_connect函數發送SYN包*/
err = sk->prot->connect(sk, uaddr, addr_len);
if (err < 0) //出錯則退出
goto out;
sock->state = SS_CONNECTING;
/* 此處僅設置socket的狀態為SS_CONNECTING表示連接狀態正在處理;
* 不同之處在於非阻塞情況下,返回值設置為-EINPROGRESS表示操作正在處理
* 而阻塞式情況則在獲得ACK包後將返回值置為-EALREADY.
*/
err = -EINPROGRESS;
break;
}

timeo = sock_sndtimeo(sk, flags&O_NONBLOCK); //注意,如果此時設置了非阻塞選項,則timeo返回0
//如果socket對應的sock狀態是SYN包已發送或收到SYN包並發送了ACK包,並等待對端發送第三此的ACK包
if ((1<<sk->state)&(TCPF_SYN_SENT|TCPF_SYN_RECV)) {
/* 錯誤返回碼err前面已經設置 */
if (!timeo || !inet_wait_for_connect(sk, timeo))
/*注意上面所判斷的2中情況,1、如果是非阻塞模式,則!timeo為1,則直接跳到out返回-EINPROGRESS結束connect函數
2、若為阻塞模式,則在inet_wait_for_connect函數中通過schele_timeout函數放棄cpu控制權睡眠,等待伺服器端
發送ACK響應包後被喚醒繼續處理。如果沒有異常出現,則置socket狀態為SS_CONNECTED,表示連接成功,正確返回
*/
goto out;

err = sock_intr_errno(timeo);
if (signal_pending(current)) /*處理未決信號*/
goto out;
}
...
sock->state = SS_CONNECTED;
err = 0;
out:
release_sock(sk);
return err;
...
上面的描述有一個問題:對伺服器的響應ACK包是什麼時候發送的?對於非阻塞模式,應該是應用處理過程中
的某個非同步時間;對於阻塞模式,則是在inet_wait_for_connect函數中睡眠時處理。
即網卡在收到對方的ack包後,上傳給對應的socket時發送伺服器的響應ACK包
函數調用鏈為:netif_rx-->net_rx_action-->...(IP層處理)-->tcp_v4_rcv-->tcp_v4_do_rcv-->
tcp_rcv_state_process-->tcp_rcv_synsent_state_process-->tcp_send_synack-->tcp_transmit_skb...
發送SYN包後,socket對應的sock的狀態變成TCPF_SYN_SENT,網卡收到伺服器的ack傳到tcp層時,根據TCPF_SYN_SENT
狀態,做相關判斷後再發送用於第三次握手的ack包。至此,將socket的狀態改為連接建立,即TCP_ESTABLISHED。
具體的代碼大家可以根據我提供的函數調用鏈查看。
注意,以TCPF_前綴開頭的狀態都表示是中間狀態,而已TCP_為前綴的狀態才是socket的一個相對穩定的狀態。

這里有一個疑問,,根據接收處理源碼,先前的SYN包應該發送給伺服器的監聽socket,而第三次握手似乎應該發送給
連接(未真正連接,因為三次握手還沒完成呢)的socket,這個問題有待進一步確認
三、伺服器端支持
伺服器端此時必須是監聽狀態,則其函數調用鏈為:
netif_rx-->net_rx_action-->...(IP層處理)-->tcp_v4_rcv-->tcp_v4_do_rcv-->
tcp_rcv_state_process-->tcp_v4_conn_request-->tcp_v4_send_synack...
在tcp_v4_conn_request,中部分代碼如下:
...
case TCP_LISTEN:
if(th->ack) /*監聽時收到的ack包都丟棄?*/
return 1;
if(th->syn) {/*如果是SYN包,則調用tcp_v4_conn_request*/
if(tp->af_specific->conn_request(sk, skb) < 0)
return 1;

9. 如何優化 linux 內核參數設置tcp

其實也不能算是原創,日常工作的時候經常和這些參數打交道,遇到不明白的就去網上找到並記錄下來,零零散散的記錄了這么多,呵呵,如果你遇到沒見過的參數,不妨來我這里找找,如果有不準確的地方,還請大家回復指出,謝謝 $ /proc/sys/net/core...

熱點內容
人間地獄為什麼沒有伺服器 發布:2025-01-18 05:20:07 瀏覽:442
c語言編譯器的版權 發布:2025-01-18 05:13:37 瀏覽:296
htmlbase64圖片上傳 發布:2025-01-18 05:13:03 瀏覽:19
微信小程序源碼目錄 發布:2025-01-18 05:08:51 瀏覽:679
投影儀什麼配置好 發布:2025-01-18 05:01:46 瀏覽:56
傾城密碼有什麼蛋糕 發布:2025-01-18 05:00:35 瀏覽:413
安卓應用鎖是什麼意思 發布:2025-01-18 04:59:57 瀏覽:908
mfc數據存儲 發布:2025-01-18 04:59:05 瀏覽:570
今日頭條as演算法 發布:2025-01-18 04:53:05 瀏覽:6
設置js緩存時間 發布:2025-01-18 04:43:44 瀏覽:512