新聞中心
在Linux系統(tǒng)中,TCP socket綁定端口(bind)的操作是非常常見的。然而,有時候我們希望在綁定新端口之前關閉當前正在使用的端口連接,以確保新的TCP連接正常工作。本文將介紹如何在Linux系統(tǒng)中實現(xiàn)此操作。

通榆網(wǎng)站建設公司創(chuàng)新互聯(lián),通榆網(wǎng)站設計制作,有大型網(wǎng)站制作公司豐富經(jīng)驗。已為通榆上千多家提供企業(yè)網(wǎng)站建設服務。企業(yè)網(wǎng)站搭建\成都外貿(mào)網(wǎng)站建設要多少錢,請找那個售后服務好的通榆做網(wǎng)站的公司定做!
1. 使用SO_REUSEADDR選項
SO_REUSEADDR選項可以讓我們在綁定新的端口之前,先關閉當前端口連接。在使用SO_REUSEADDR選項時,我們需要注意以下幾點:
– 該選項需要在socket創(chuàng)建時就設置,因此我們需要使用setsockopt函數(shù)設置該選項:
“`
int on = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))
perror(“setsockopt”);
exit(1);
}
“`
– 在使用SO_REUSEADDR選項時,close函數(shù)并不會立即關閉socket連接,而是將其標記為“等待連接中”。因此,我們需要使用shutdown函數(shù)主動關閉連接:
“`
shutdown(sockfd, SHUT_RDWR);
close(sockfd);
“`
– 在調(diào)用shutdown函數(shù)之前,需要確保socket已經(jīng)完成了初始化等操作,否則可能會導致程序異常退出。
– 如果我們正在監(jiān)聽一個端口,那么在使用SO_REUSEADDR選項時可能會遇到“端口忙”的問題。此時,我們可以使用SO_REUSEPORT選項解決:
“`
int on = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &on, sizeof(on))
perror(“setsockopt”);
exit(1);
}
“`
2. 使用bind函數(shù)的SO_EXCLUSIVEADDRUSE選項
SO_EXCLUSIVEADDRUSE選項可以確保在綁定新端口之前,當前端口連接已經(jīng)關閉。使用SO_EXCLUSIVEADDRUSE選項時,我們需要注意以下幾點:
– 該選項需要在bind函數(shù)中設置,因此我們需要使用bind函數(shù)的第三個參數(shù)(struct sockaddr *addr)來設置該選項:
“`
int on = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, &on, sizeof(on))
perror(“setsockopt”);
exit(1);
}
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
if(bind(sockfd, (struct sockaddr*)&addr, sizeof(addr))
perror(“bind”);
exit(1);
}
“`
– 由于在調(diào)用setsockopt函數(shù)后必須緊接著調(diào)用bind函數(shù),因此在使用SO_EXCLUSIVEADDRUSE選項時,我們不能使用listen函數(shù)來監(jiān)聽socket,否則程序可能會在setsockopt函數(shù)返回之前就退出。
– 使用SO_EXCLUSIVEADDRUSE選項時,即使連接已經(jīng)關閉,bind函數(shù)也可能會返回EADDRINUSE錯誤。此時,我們可以使用SO_REUSEADDR選項。另外,有些Linux內(nèi)核版本需要在sysctl中修改net.ipv4.tcp_tw_reuse參數(shù),才能正常使用SO_REUSEADDR選項。
本文介紹了在Linux系統(tǒng)中實現(xiàn)TCP重新綁定端口前先關閉連接的兩種方法。使用SO_REUSEADDR選項比較簡單,但是需要注意一些細節(jié)問題;使用SO_EXCLUSIVEADDRUSE選項比較靈活,可以確保當前端口連接已經(jīng)關閉,但是需要更多的配置和控制。在具體使用時,我們應該根據(jù)實際應用場景來選擇合適的方法。
成都網(wǎng)站建設公司-創(chuàng)新互聯(lián)為您提供網(wǎng)站建設、網(wǎng)站制作、網(wǎng)頁設計及定制高端網(wǎng)站建設服務!
暢談linux下TCP(上)
tcp 協(xié)議 是互聯(lián)網(wǎng)中最常用的協(xié)議 , 開發(fā)人員基本上天天和它打交道,對它進行深入了解。 可以幫助我們排查定位bug和進行程序優(yōu)化。下面我將就TCP幾個點做深入的探討
客戶端:收到 ack 后 分配連接資源。 發(fā)送數(shù)據(jù)
服務器 : 收到 syn 后立即 分配連接資源
客戶端:收到ACK, 立即分配資源
服務器:收到ACK, 立即分配資源
既然三次握手也液銀顫不是100%可靠, 那四次,五次,六次。呢? 其實都一樣,不管多少次都有丟包問題。
client 只發(fā)送一個 SYN, server 分配一個tcb, 放入syn隊列中。 這時候連接叫
半連接
狀態(tài);如果server 收不到 client 的ACK, 會不停重試 發(fā)送 ACK-SYN 給client 。重試間隔 為 2 的 N 次方 疊加(2^0 , 2^1, 2^2 ….);直至超時才釋放syn隊列中的這個 TCB;
在半連接狀態(tài)下, 一方面會占用隊列配額資源,另一方面占用內(nèi)存資源。我們應該讓半連接狀態(tài)存在時間盡可能的小
當client 向一個未打開的端口發(fā)起連接請求時,會收到一個RST回復包
當listen 的 backlog 和 somaxconn 都設置了得時候, 取兩者min值
Recv-Q 是accept 隊列當前個數(shù), Send-Q 設置更大值
這種SYN洪水攻擊是一種常見攻擊方式,就是利用半連接隊列特性,占滿syn 隊列的 資源,導致 client無法連接上。
解決方案:
為什么不像握手那樣合并成三次揮手? 因為和剛開始連接情況,連接是大家都從0開始, 關閉時有歷史包袱的。server(被動關閉方) 收到 client(主動關閉方) 的關閉請求FIN包。 這時候可能還有未發(fā)送完的數(shù)據(jù),不能丟棄。 所以需要分開。事實可能是這樣
當然,在沒有待發(fā)數(shù)據(jù),并且允許 Delay ACK 情況下, FIN-ACK合并還是非常常見的事情,這是三次揮手是可以的。
同上
CLOSE_WAIT 是被動關閉方才有的狀態(tài)
。
被動關閉方 到 期間的狀態(tài)為 CLOSE_WAIT, 這個狀態(tài)仍然能發(fā)鬧敗送數(shù)據(jù)。 我們叫做
半關閉
, 下面用個例子來分析:
這個是我實際生產(chǎn)環(huán)境碰到的一個問題,長連接會話場景,server端收到client的rpc call 請求1,處理發(fā)現(xiàn)請求包有問題,就強制關閉結束這次會話, 但是 因為client 發(fā)送 第二次請求之前,并沒有去調(diào)用recv,所以并不知道 這個連接被server關閉, 繼續(xù)發(fā)送 請求2 , 此時是半連接,能夠成功發(fā)送到對端機器,但是recv結果后,搏兆遇到連接已經(jīng)關閉錯誤。
如果 client 和 server 恰好同時發(fā)起關閉連接。這種情況下,兩邊都是主動連接,都會進入 TIME_WAIT狀態(tài)
1、
被動關閉方在LAST_ACK狀態(tài)(已經(jīng)發(fā)送FIN),等待主動關閉方的ACK應答,但是 ACK丟掉, 主動方并不知道,以為成功關閉。因為沒有TIME_WAIT等待時間,可以立即創(chuàng)建新的連接, 新的連接發(fā)送SYN到前面那個未關閉的被動方,被動方認為是收到錯誤指令,會發(fā)送RST。導致創(chuàng)建連接失敗。
2、
主動關閉方斷開連接,如果沒有TIME_WAIT等待時間,可以馬上建立一個新的連接,但是前一個已經(jīng)斷開連接的,延遲到達的數(shù)據(jù)包。 被新建的連接接收,如果剛好seq 和 ack字段 都正確, seq在滑動窗口范圍內(nèi)(只能說機率非常小,但是還是有可能會發(fā)生),會被當成正確數(shù)據(jù)包接收,導致數(shù)據(jù)串包。 如果不在window范圍內(nèi),則沒有影響( 發(fā)送一個確認報文(ack 字段為期望ack的序列號,seq為當前發(fā)送序列號),狀態(tài)變保持原樣)
TIME_WAIT 問題比較比較常見,特別是CGI機器,并發(fā)量高,大量連接后段服務的tcp短連接。因此也衍生出了多種手段解決。雖然每種方法解決不是那么完美,但是帶來的好處一般多于壞處。還是在日常工作中會使用。
1、改短TIME_WAIT 等待時間
這個是之一個想到的解決辦法,既然等待時間太長,就改成時間短,快速回收端口。但是實際情況往往不樂觀,對于并發(fā)的機器,你改多短才能保證回收速度呢,有時候幾秒鐘就幾萬個連接。太短的話,就會有前面兩種問題小概率發(fā)生。
2、禁止Socket lingering
這種情況下關閉連接,會直接拋棄緩沖區(qū)中待發(fā)送的數(shù)據(jù),會發(fā)送一個RST給對端,相當于直接拋棄TIME_WAIT, 進入CLOSE狀態(tài)。同樣因為取消了 TIME_WAIT 狀態(tài),會有前面兩種問題小概率發(fā)生。
3、tcp_tw_reuse
net.ipv4.tcp_tw_reuse選項是 從 TIME_WAIT 狀態(tài)的隊列中,選取條件:1、remote 的 ip 和端口相同, 2、選取一個時間戳小于當前時間戳; 用來解決端口不足的尷尬。
現(xiàn)在端口可以復用了,看看如何面對前面TIME_WAIT 那兩種問題。 我們仔細回顧用一下前面兩種問題。
都是在新建連接中收到老連接的包導致的問題
, 那么如果我能在新連接中識別出此包為非法包,是不是就可以丟掉這些無用包,解決問題呢。
需要實現(xiàn)這些功能,需要擴展一下tcp 包頭。 增加 時間戳字段。 發(fā)送者 在每次發(fā)送的時候。 在tcp包頭里面帶上發(fā)送時候的時間戳。 當接收者接收的時候,在ACK應答中除了TCP包頭中帶自己此時發(fā)送的時間戳,并且把收到的時間戳附加在后面。也就是說ACK包中有兩個時間戳字段。結構如下:
那我們接下來一個個分析tcp_tw_reuse是如何解決TIME_WAIT的兩個問題的
4、tcp_tw_recycle
tcp_tw_recycle 也是借助 timestamp機制。顧名思義, tcp_tw_reuse 是復用 端口,并不會減少 TIME-WAIT 數(shù)量。你去查詢機器上TIME-WAIT 數(shù)量,還是 幾千幾萬個,這點對有強迫癥的同學感覺很不舒服。tcp_tw_recycle 是 提前 回收 TIME-WAIT資源。會減少 機器上 TIME-WAIT 數(shù)量。
關于linux tcp 關閉再bind的介紹到此就結束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關注本站。
香港服務器選創(chuàng)新互聯(lián),香港虛擬主機被稱為香港虛擬空間/香港網(wǎng)站空間,或者簡稱香港主機/香港空間。香港虛擬主機特點是免備案空間開通就用, 創(chuàng)新互聯(lián)香港主機精選cn2+bgp線路訪問快、穩(wěn)定!
網(wǎng)頁題目:LinuxTCP重新綁定端口前先關閉連接的方法(linuxtcp關閉再bind)
文章鏈接:http://www.5511xx.com/article/dhscghe.html


咨詢
建站咨詢
