setsockopt設定埠複用的作用(bind繫結失敗)
阿新 • • 發佈:2018-12-29
本文轉自:http://www.2cto.com/kf/201208/150347.html
寫Socket程式的時候經常會遇到這個問題:如果自己的程式不小心崩潰了,重新啟動程式的時候往往會在bind呼叫上失敗,錯誤原因為Address Already In Use,往往要等待兩分鐘才能再次繫結。但是在很多的程式(比如nginx)中好像並不存在這個問題,就算被KILL了也能立刻重啟。這個區別還是比較頭痛的。
其實我猜Unix Socket程式設計這樣的書上有討論過這方面的問題,不過我竟然沒有這方面的書籍(完全靠man看來也是行不通啊)。我曾經天真的以為,在收到SIGTERM這樣的訊號的時候把所有套接字全部關閉可以解決問題。後來才發現無濟於事。Google了這方面的文章才知道,解決這個問題理論上有三種辦法。
s = socket(AF_INET, SOCK_STREAM, 0);
/* What you need to do is add the following two line to your code */
unsigned value = 1;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));
/* Then do other things */listen(s, SOMAXCONN);/* ... */
而解決這個安全性的問題的方法其實也不難(其實換個沒問題的作業系統就可以了不是?),只要把套接字繫結繫結到具體的網路裝置的IP地址(比如繫結到127.0.0.1,或者a.b.c.d)即可,大不了為每個網路裝置建一個套接字。如果實施起來有難度,只能考慮後面的兩種方法。
3.讓客戶端先關閉連線。如果所有的連線關閉事件都在客戶端首先發生,那麼也不會存在這個問題。不過這種做法可能需要修改協議,而且貌似很容易惡意連線攻擊。修改系統TCP超時時間,這種方法很不推薦。