1. 程式人生 > >Linux網路程式設計socket選項之SO_LINGER,SO_REUSEADDR

Linux網路程式設計socket選項之SO_LINGER,SO_REUSEADDR

Linux網路程式設計中,socket的選項很多.其中幾個比較重要的選項有:SO_LINGER(僅僅適用於TCP,SCTP), SO_REUSEADDR.

  • SO_LINGER

在預設情況下,當呼叫close關閉socke的使用,close會立即返回,但是,如果send buffer中還有資料,系統會試著先把send buffer中的資料傳送出去,然後close才返回.

SO_LINGER選項則是用來修改這種預設操作的.與SO_LINGER相關聯的一個結構體如下:

[cpp] view plaincopyprint?
  1. #include <sys/socket.h>
  2. struct
    linger { 
  3.       int l_onoff    //0=off, nonzero=on(開關)
  4.       int l_linger   //linger time(延遲時間)

當呼叫setsockopt之後,該選項產生的影響取決於linger結構體中 l_onoff和l_linger的值:

1、0 = l_onoff

       當l_onoff被設定為0的時候,將會關閉SO_LINGER選項,即TCP或則SCTP保持預設操作:close立即返回.l_linger值被忽略.

2、l_lineoff值非0,0 = l_linger

       當呼叫close的時候,TCP連線會立即斷開.send buffer中未被髮送的資料將被丟棄,並向對方傳送一個RST資訊.值得注意的是,由於這種方式,是非正常的4中握手方式結束TCP連結,所以,TCP連線將不會進入TIME_WAIT狀態,這樣會導致新建立的可能和就連線的資料造成混亂。具體原因詳見我的上一篇文章《linux 網路程式設計之TIME_WAIT狀態》

3、l_onoff和l_linger都是非0

       在這種情況下,回事的close返回得到延遲。呼叫close去關閉socket的時候,核心將會延遲。也就是說,如果send buffer中還有資料尚未傳送,該程序將會被休眠直到一下任何一種情況發生:

1)    send buffer中的所有資料都被髮送並且得到對方TCP的應答訊息(這種應答並不是意味著對方應用程式已經接收到資料,在後面shutdown將會具體講道)
2)    延遲時間消耗完。在延遲時間被消耗完之後,send buffer中的所有資料都將會被丟棄。

上面1),2)兩種情況中,如果socket被設定為O_NONBLOCK狀態,程式將不會等待close返回,send buffer中的所有資料都將會被丟棄。所以,需要我們判斷close的返回值。在send buffer中的所有資料都被髮送之前並且延遲時間沒有消耗完,close返回的話,close將會返回一個EWOULDBLOCK的error.

下面用幾個例項來說明:


A.    Close預設操作:立即返回

                                         

此種情況,close立即返回,如果send buffer中還有資料,close將會等到所有資料被髮送完之後之後返回。由於我們並沒有等待對方TCP傳送的ACK資訊,所以我們只能保證資料已經發送到對方,我們並不知道對方是否已經接受了資料。由於此種情況,TCP連線終止是按照正常的4次握手方式,需要經過TIME_WAIT。

   B.    l_onoff非0,並且使之l_linger為一個整數

                                        

在這種情況下,close會在接收到對方TCP的ACK資訊之後才返回(l_linger消耗完之前)。但是這種ACK資訊只能保證對方已經接收到資料,並不保證對方應用程式已經讀取資料。

C.    l_linger設定值太小

                                          

這種情況,由於l_linger值太小,在send buffer中的資料都發送完之前,close就返回,此種情況終止TCP連線,更l_linger = 0類似,TCP連線終止不是按照正常的4步握手,所以,TCP連線不會進入TIME_WAIT狀態,那麼,client會向server傳送一個RST資訊.

D.    Shutdown,等待應用程式讀取資料

                                        

同上面的B進行對比,呼叫shutdown後緊接著呼叫read,此時read會被阻塞,直到接收到對方的FIN,也就是說read是在server的應用程式呼叫close之後才返回的。當server應用程式讀取到來自client的資料和FIN之後,server會進入一個叫CLOSE_WAIT,關於CLOSE_WAIT,詳見我的部落格《 Linux 網路程式設計 之 TCP狀態轉換》 。那麼,如果server端要斷開該TCP連線,需要server應用程式呼叫一次close,也就意味著向client傳送FIN。這個時候,說明server端的應用程式已經讀取到client傳送的資料和FIN。read會在接收到server的FIN之後返回。所以,shutdown 可以確保server端應用程式已經讀取資料了,而不僅僅是server已經接收到資料而已。

shutdown引數如下:

SHUT_RD:呼叫shutdown的一端receive buffer將被丟棄掉,無法接受資料,但是可以傳送資料,send buffer的資料可以被髮送出去

SHUT_WR:呼叫shutdown的一端無法傳送資料,但是可以接受資料.該引數表示不能呼叫send.但是如果還有資料在send buffer中,這些資料還是會被繼續傳送出去的.

  • SO_REUSEADDR和SO_REUSEPORT

最近,看到CSDN的linux版塊,有人提問,說為什麼server程式重啟之後,無法連線,需要過一段時間才能連線上.我想對於這個問題,有兩種可能:一種可能就是該server一直停留在TIME_WAIT狀態.這個時候,需要等待2MSL的時間才能重新連線上,具體細節原因請見我的另一篇文章《linux 網路程式設計之TIME_WAIT狀態》

另一種可能就是SO_REUSEADDR引數設定問題.關於TIME_WAIT的我就不在這裡重述了,這裡我講一講SO_REUSEADDR.

  • SO_REUSEADDR允許一個server程式listen監聽並bind到一個埠,既是這個埠已經被一個正在執行的連線使用了.

我們一般會在下面這種情況中遇到:

  1. 一個監聽(listen)server已經啟動
  2. 當有client有連線請求的時候,server產生一個子程序去處理該client的事物.
  3. server主程序終止了,但是子程序還在佔用該連線處理client的事情.雖然主程序終止了,但是由於子程序沒有終止,該socket的引用計數不會為0,所以該socket不會被關閉.
  4. server程式重啟.

預設情況下,server重啟,呼叫socket,bind,然後listen,會失敗.因為該埠正在被使用.如果設定SO_REUSEADDR,那麼server重啟才會成功.因此,所有的TCP server都必須設定此選項,用以應對server重啟的現象.

  • SO_REUSEPORT允許同一個埠上繫結多個IP.只要這些IP不同.另外,還可以在繫結IP萬用字元.但是最好是先繫結確定的IP,最後繫結萬用字元IP.以免系統拒絕.簡而言之,SO_REUSEPORT允許多個server繫結到同一個port上,只要這些server指定的IP不同,但是SO_REUSEPORT需要在bind呼叫之前就設定.在TCP中,不允許建立起一個已經存在的相同的IP和埠的連線.但是在UDP中,是允許的.

相關推薦

Linux網路程式設計socket選項SO_LINGER,SO_REUSEADDR

Linux網路程式設計中,socket的選項很多.其中幾個比較重要的選項有:SO_LINGER(僅僅適用於TCP,SCTP), SO_REUSEADDR. SO_LINGER 在預設情況下,當呼叫close關閉socke的使用,close會立即返回,但是,如果send

linux網路程式設計——Socket

//server #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h&g

linux 網路程式設計 socket bind failed 問題解決

int sock, ret, on; struct sockaddr_in servaddr; /* Create a new stream (TCP) socket */ sock = socket( AF_INET, SOCK_STREAM, 0 ): /* Enable address reuse *

Linux網路程式設計socket錯誤分析

轉自: http://aigo.iteye.com/blog/1911134 socket錯誤碼: EINTR: 4 阻塞的操作被取消阻塞的呼叫打斷。如設定了傳送接收超時,就會遇到這種錯誤。 只能針對阻塞模式的socket。讀,寫阻塞的socket時,-1返回,錯誤號為

linux網路程式設計四:socket選項SO_REUSEADDR, SO_RCVBUF, SO_SNDBUF

最近在看《linux高效能伺服器程式設計》,在此做個日記,以激勵自己,同時分享於有需要的朋友。 1. 讀取和設定socket檔案描述符屬性: #include <sys/socket.h> int getsockopt(int sockfd, int lev

linux網路程式設計socket實現簡單客戶端和服務端的通訊(基於TCP)

一、介紹基於TCP協議通過socket實現網路程式設計常用API 1、讀者如果不是很熟悉,可以先看我之前寫的幾篇部落格,有socket,地址結構的理解,更加方便讀者理解 地址分別是: 2、socket(TCP)程式設計API簡介 1)、socket int s

linux網路程式設計socket實現簡單客戶端和服務端的通訊(基於UDP)

1、sendto和recvfrom函式介紹 sendto(經socket傳送資料) 相關函式 send , sendmsg,recv , recvfrom , socket 表頭檔案 #include < sys/types.h >#includ

Linux網路程式設計套接字選項設定

轉自 http://blog.csdn.net/chenjin_zhong/article/details/7268939 1.介紹 在Linux網路程式設計中,有時需要設定地址複用,允許傳送廣播包,將主機加入某個多播組,設定傳送與接收緩衝區的大小,設定傳送與接收的超

Linux網路程式設計Tcp/Udp socket檔案傳輸示例

本文所述示例程式是基於Linux平臺的socket網路程式設計,實現檔案傳輸功能。該示例是基於TCP流協議實現的socket網路檔案傳輸程式。採用C語言編寫。最終能夠實現傳輸任何格式檔案的檔案傳輸程式。 具體實現程式碼如下: /***********************

linux網路程式設計socket(十六):通過UNIX域套接字傳遞描述符和 sendmsg/recvmsg 函式

void send_fd(int sock_fd, int send_fd) {     int ret;     struct msghdr msg;     struct cmsghdr *p_cmsg;     struct iovec vec;     char cmsgbuf[CMSG_SPACE(

linux網路程式設計二十:socket選項:SO_RCVTIMEO和SO_SNDTIMEO

SO_RCVTIMEO和SO_SNDTIMEO ,它們分別用來設定socket接收資料超時時間和傳送資料超時時間。 因此,這兩個

小猿圈linux網路程式設計--socket建立

網路程式設計離不開socket,小猿圈這篇詳解一下socket建立,仔細學完這篇對你認識網路底層的東西有著很重要的作用,同時即便有

Linux網路程式設計:TCP客戶/伺服器模型及基本socket函式

TCP客戶/伺服器模型 TCP連線的分組交換 在使用socket API的時候應該清楚應用程式和TCP協議棧是如何互動的: 呼叫connect()會發出SYN段(SYN是TCP報文段頭部的一個標誌位,置為1) 阻塞的read()函式返回0就表明收到了FIN段 客戶端呼叫c

Linux網路程式設計socket程式設計簡介、網路位元組序及相關函式

Socket(套接字) socket可以看成是使用者程序與核心網路協議棧的程式設計介面(API函式)。 socket不僅可以用於本機的程序間通訊,還可以用於網路上不同主機的程序間通訊。 IPv4套接字地址結構 IPv4套接字地址結構通常也稱為“網際套接字地址結構”,它以

Linux網路程式設計---I/O多路複用select

1.I/O多路複用(IO multiplexing) 我們之前講了I/O多路複用和其他I/O的區別,在這裡,我們再具體討論下I/O多路複用是怎麼工作? I/O 多路複用技術就是為了解決程序或執行緒阻塞到某個 I/O 系統呼叫而出現的技術,使程序不阻塞於某個特定的 I/O 系統呼叫。

linux 網路程式設計廣播

linux 網路程式設計之廣播 轉載:https://blog.csdn.net/qdlovecsj/article/details/8805483 廣播方式主要是指使用UDP套介面傳送資料,傳送資料的目標地址不是普通的地址,而是所指定網路的廣播地址。 什麼是廣播地址?是指IP地

Linux網路程式設計TCP程式設計

直接上程式碼如下所示: 1、標頭檔案定義 #ifndef __HEAD_NET_H__ #define __HEAD_NET_H__ #include <stdio.h> #include <string.h> #include <stdlib.h>

Linux網路程式設計IO模型

本文基於IO訪問中存在的兩個階段詳細介紹了Linux產生的五種IO模型。 上篇文章回顧: 小米開源監控Open-Falcon收錄汽車之家貢獻的Win版Agent 同步與非同步 同步是指一個任務的完成需要依賴另外一個任務時,只有等待被依賴的任務完成後

linux網路程式設計多程序併發伺服器

1)使用多程序併發伺服器考慮的因素:       (1)父程序描述最大檔案描述符的個數(父程序需要關閉accept返回的新檔案描述符)       (2)系統內可建立程序的個數(與記憶體大小相關)       (3)程序建立過多是否降低整體服務效能 2)多程序建立併發

linux網路程式設計TCP狀態轉換及埠複用

(1)TCP狀態轉換圖               其中圖中分為三種狀態:實線代表的主動發起連線,虛線代表的被動發起連線,細實線代表的可以雙向發起連線的狀態。 主動發起連線方狀態變化:1)主動發起連線的一方傳送SYN標誌位,進入SYN_SENT狀態,等待接收被髮起連線方