UNIX 網絡編程 chapter 7 (useless)

7.5.11 SO_REUSEADDR & SO_REUSEPORT

SO_REUSEADDR

做用1
  當沒有設置SO_REUSEADDR的時候,socketA先綁定到0.0.0.0:21,而後socketB綁定到192.168.0.1:21的時候將會失敗(EADDRINUSE錯誤),由於0.0.0.0意味着"任意本地IP地址」,也就是"全部本地IP地址「,所以包括192.168.0.1在內的全部IP地址都被認爲是已經使用了。可是在設置SO_REUSEADDR以後socketB的綁定將會成功,由於0.0.0.0和192.168.0.1事實上不是同一個IP地址,一個是表明全部地址的通配地址,另外一個是一個具體的地址。注意上面的表述對於socketA和socketB的綁定順序是無關的,沒有設置SO_REUSEADDR,它們將失敗,設置了SO_REUSEADDR,它將成功。服務器

做用2
  將服務器關閉後,實際上關閉了服務器的監聽套接字(close),若是此時用戶點擊開啓服務器,那麼用戶但願的狀況是服務器又當即啓動了。因爲close後,執行了主動關閉,執行主動關閉的一端,在客戶執行被動關閉以後會經歷TIME_WAIT狀態,如上圖。TIME_WAIT的時間爲1-4分鐘不等,當某端口處於TIME_WAIT狀態時,是沒法被綁定的(bind).若是在項目中用戶關閉服務器後,但願當即啓動,而程序卻要等1-4分鐘不等的時間後才能從新啓動服務器明顯不是咱們所但願的。SO_REUSEADDR套接字選項就能夠用來解決這個問題,實現瞬間重啓服務器.
注意
  SO_REUSEADDR須要在每次socket和bind前調用,「每次」也就是說,不能再想要重用的那一次,對經過socket新獲取的套接字啓用,例如socket->bind->close進入TIME_WAIT,而此時想要在TIME_WAIT狀態下綁定,那麼接下來sock->setsockopt->bind,bind是不會成功的,或者只覺得綁定的是同一個地址,就只第一次啓用一次,也是不行的。即便是第一次得到的套接字不須要重用,也要啓用該選項,這樣後面每次啓用纔會達到預期效果。socket

SO_REUSEPORT

  SO_REUSEPORT的含義與絕大部分人對SO_REUSEADDR的理解同樣。基本上說來,SO_REUSEPORT容許你將多個socket綁定到相同的地址和端口, 只要它們在綁定以前都設置了SO_REUSEPORT。若是第一個綁定某個地址和端口的socket沒有設置SO_REUSEPORT,那麼其餘的socket不管有沒有設置SO_REUSEPORT都沒法綁定到該地址和端口直到第一個socket釋放了綁定。
  SO_REUSEPORT並不表示SO_REUSEADDR。這意味着若是一個socket在綁定時沒有設置SO_REUSEPORT,那麼同預期的同樣,其它的socket對相同地址和端口的綁定會失敗,可是若是綁定相同地址和端口的socket正處在TIME_WAIT狀態,新的綁定也會失敗。當有個socket綁定後處在TIME_WAIT狀態(釋放時)時,爲了使得其它socket綁定相同地址和端口可以成功,須要設置SO_REUSEADDR或者在這兩個socket上都設置SO_REUSEPORT。固然,在socket上同時設置SO_REUSEPORT和SO_REUSEADDR也是可行的。code

相關文章
相關標籤/搜索