国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

深入剖析阻塞式socket的timeout

這篇具有很好參考價(jià)值的文章主要介紹了深入剖析阻塞式socket的timeout。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

1、前言


網(wǎng)絡(luò)編程中超時(shí)時(shí)間是一個(gè)重要但又容易被忽略的問(wèn)題,對(duì)其的設(shè)置需要仔細(xì)斟酌。

本文討論的是socket設(shè)置為阻塞模式,如果socket處于阻塞模式運(yùn)行時(shí),就需要考慮處理socket操作超時(shí)的問(wèn)題。所謂阻塞模式,是指其完成指定的操作之前阻塞當(dāng)前的進(jìn)程或線(xiàn)程,直到操作有結(jié)果返回.在我們直接調(diào)用socket操作函數(shù)時(shí),如果不進(jìn)行特意聲明的話(huà),它們都是工作在阻塞模式的,如 connect, send, recv等.

簡(jiǎn)單分類(lèi)的話(huà),可以將超時(shí)處理分成兩類(lèi):

連接(connect)超時(shí);發(fā)送(send), 接收(recv)超時(shí);

2、連接超時(shí)


從字面上看,連接超時(shí)就是在一定時(shí)間內(nèi)還是連接不上目標(biāo)主機(jī)。你所建立的socket連接其實(shí)最終都要進(jìn)行系統(tǒng)調(diào)用進(jìn)入內(nèi)核態(tài),剩下的就是等待內(nèi)核通知連接建立。所以自行在代碼中設(shè)置了超時(shí)時(shí)間(一般是叫connectTimeout或者socketTimeout),那么這個(gè)超時(shí)時(shí)間一到如果內(nèi)核還沒(méi)成功建立連接,那就認(rèn)為是連接超時(shí)了。如果他們沒(méi)設(shè)置超時(shí)時(shí)間,那么這個(gè)connectTimeout就取決于內(nèi)核什么時(shí)候拋出超時(shí)異常了。

因此,我們需要分析一下內(nèi)核是怎么來(lái)判斷連接超時(shí)的。

2.1內(nèi)核層的超時(shí)分析

我們都知道一個(gè)連接的建立需要經(jīng)過(guò)3次握手,所以連接超時(shí)簡(jiǎn)單的說(shuō)是是客戶(hù)端往服務(wù)端發(fā)的SYN報(bào)文沒(méi)有得到響應(yīng)(服務(wù)端沒(méi)有返回ACK報(bào)文)。

由于網(wǎng)絡(luò)本身是不穩(wěn)定的,丟包是很常見(jiàn)的事情(或者對(duì)方主機(jī)因?yàn)槟承┰騺G棄了該包),因此內(nèi)核在發(fā)送SYN報(bào)文沒(méi)有得到響應(yīng)后,往往還是進(jìn)行多次重試。同時(shí),為了避免發(fā)送太多的包影響網(wǎng)絡(luò),重試的時(shí)間間隔還會(huì)不斷增加。

在linux中,重試的時(shí)間間隔會(huì)呈指數(shù)型增長(zhǎng),為2的N次方,即:

第一次發(fā)送SYN報(bào)文后等待1s(2的0次冪)后再重試

第二次發(fā)送SYN報(bào)文后等待2s(2的1次冪)后再重試

第三次發(fā)送SYN報(bào)文后等待4s(2的2次冪)后再重試

第四次發(fā)送SYN報(bào)文后等待8s(2的3次冪)后再重試

第五次發(fā)送SYN報(bào)文后等待16s(2的4次冪)后再重試

第六次發(fā)送SYN報(bào)文后等待32s(2的5次冪)后再重試

第七次發(fā)送SYN報(bào)文后等待64s(2的6次冪)后再重試

對(duì)于重試次數(shù),由linux的net.ipv4.tcp_syn_retries來(lái)確定,默認(rèn)值一般是6(有些linux發(fā)行版可能不太一樣),我們可以通過(guò)sysctl net.ipv4.tcp_syn_retries查看。比如重試次數(shù)是6次,那么我們可以得出超時(shí)時(shí)間應(yīng)該是 1+2+4+8+16+32+64=127秒 (上面的第一條是第一次發(fā)送SYN報(bào)文,不算重試)。

如果我們想修改重試次數(shù),可以輸入命令sysctl -w net.ipv4.tcp_syn_retries=5來(lái)修改(需要root權(quán)限)。如果希望重啟后生效,將net.ipv4.tcp_syn_retries = 5放入/etc/sysctl.conf中,之后執(zhí)行sysctl -p 即可生效。

在一些linux發(fā)行版中,重試時(shí)間可能會(huì)變動(dòng)。如果想確定操作系統(tǒng)具體的超時(shí)時(shí)間,可以通過(guò)下面這條命令來(lái)判斷:

gaoke@ubuntu:~$ date; telnet 10.16.15.15 5000; date

Sat Apr 2 14:27:33 CST 2022

Trying 10.16.15.15...

telnet: Unable to connect to remote host: Connection timed out

Sat Apr 2 14:29:40 CST 2022

2.2綜合分析

如果應(yīng)用層面設(shè)置了自己的超時(shí)時(shí)間,同時(shí)內(nèi)核也有自己的超時(shí)時(shí)間,那么應(yīng)該以哪個(gè)為準(zhǔn)呢?答案是哪個(gè)超時(shí)時(shí)間小以哪個(gè)為準(zhǔn)。

個(gè)人認(rèn)為,在我們的實(shí)際應(yīng)用中,這個(gè)超時(shí)時(shí)間不宜設(shè)置的太長(zhǎng),通常建議2-10s。比如在分布式系統(tǒng)中,我們通常會(huì)在多臺(tái)節(jié)點(diǎn)中根據(jù)一定策略選擇一臺(tái)進(jìn)行連接。在有機(jī)器宕機(jī)的情況下,如果連接超時(shí)時(shí)間設(shè)置的比較長(zhǎng),而我們客戶(hù)端的線(xiàn)程池又比較小,就很可能大多數(shù)的線(xiàn)程都在等待建立連接,過(guò)了較長(zhǎng)時(shí)間才發(fā)現(xiàn)連接不上,影響應(yīng)用的整體吞吐量。

2.3connect系統(tǒng)調(diào)用

我們觀察一下此系統(tǒng)調(diào)用的kernel源碼,調(diào)用棧如下所示:

connect[用戶(hù)態(tài)]

|->SYSCALL_DEFINE3(connect)[內(nèi)核態(tài)]

|->sock->ops->connect

sockettimeout,音視頻開(kāi)發(fā),websocket,網(wǎng)絡(luò),音視頻,Powered by 金山文檔

最終調(diào)用的tcp_connect源碼如下:

int tcp_connect(struct sock *sk) {

......

// 發(fā)送SYN

err = tcp_transmit_skb(sk, buff, 1, sk->sk_allocation);

...

/* Timer for repeating the SYN until an answer. */

// 由于是剛建立連接,所以其rto是TCP_TIMEOUT_INIT

inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,

inet_csk(sk)->icsk_rto, TCP_RTO_MAX);

return 0;

}

又上面代碼可知,在tcp_connect設(shè)置了重傳定時(shí)器之后return回了tcp_v4_connect再return到inet_stream_connect。

我們可以采用設(shè)置SO_SNDTIMEO來(lái)控制connect系統(tǒng)調(diào)用的超時(shí),如下所示:

setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeout, len);

2.4不設(shè)置SO_SNDTIMEO

如果不設(shè)置SO_SNDTIMEO,那么會(huì)由tcp重傳定時(shí)器在重傳超過(guò)設(shè)置的時(shí)候后超時(shí),如下圖所示:

sockettimeout,音視頻開(kāi)發(fā),websocket,網(wǎng)絡(luò),音視頻,Powered by 金山文檔

我們?nèi)绾尾榭磗yn重傳次數(shù)?:

cat /proc/sys/net/ipv4/tcp_syn_retries

sockettimeout,音視頻開(kāi)發(fā),websocket,網(wǎng)絡(luò),音視頻,Powered by 金山文檔

對(duì)于系統(tǒng)調(diào)用,connect的超時(shí)時(shí)間為:

tcp_syn_retries

timeout

1

min(so_sndtimeo,3s)

2

min(so_sndtimeo,7s)

3

min(so_sndtimeo,15s)

4

min(so_sndtimeo,31s)

5

min(so_sndtimeo,63s)

kernel代碼版本細(xì)微變化

值得注意的是,linux本身官方發(fā)布的2.6.32源碼對(duì)于tcp_syn_retries2的解釋和RFC并不一致,不同內(nèi)核小版本上的實(shí)驗(yàn)會(huì)有不同的connect timeout表現(xiàn)的原因(有的抓包到的重傳SYN時(shí)間間隔為3,6,12......)。

以下為代碼對(duì)比:

========================>linux 內(nèi)核版本2.6.32-431<========================

#define TCP_TIMEOUT_INIT ((unsigned)(1*HZ)) /* RFC2988bis initial RTO value */

?

static inline bool retransmits_timed_out(struct sock *sk,

unsigned int boundary,

unsigned int timeout,

bool syn_set)

{

......

unsigned int rto_base = syn_set ? TCP_TIMEOUT_INIT : TCP_RTO_MIN;

......

timeout = ((2 << boundary) - 1) * rto_base;

......

?

}

========================>linux 內(nèi)核版本2.6.32.63<========================

#define TCP_TIMEOUT_INIT ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value */

?

static inline bool retransmits_timed_out(struct sock *sk,

unsigned int boundary

{

......

timeout = ((2 << boundary) - 1) * TCP_RTO_MIN;

......

}

另外,tcp_syn_retries重傳次數(shù)可以在單個(gè)socket中通過(guò)setsockopt設(shè)置。

3、發(fā)送超時(shí)


在tcp連接建立之后,寫(xiě)操作可以理解為向?qū)Χ税l(fā)送tcp報(bào)文的過(guò)程。在tcp的實(shí)現(xiàn)中,每一段報(bào)文都需要有對(duì)端的回應(yīng),即ACK報(bào)文。和連接時(shí)發(fā)送SYN報(bào)文一樣,如果超過(guò)一定時(shí)間沒(méi)有收到響應(yīng),內(nèi)核會(huì)再次重發(fā)該報(bào)文。和SYN報(bào)文的重試不同的是,linux有另外的參數(shù)來(lái)控制這個(gè)重試次數(shù),即net.ipv4.tcp_retries2,可以通過(guò)sysctl net.ipv4.tcp_retries2查看其值。

另外,這個(gè)數(shù)據(jù)報(bào)文重試時(shí)間間隔的計(jì)算方式也和SYN報(bào)文不一樣,由于計(jì)算方式比較復(fù)雜,這里就不詳細(xì)介紹。

一般linux發(fā)行版的net.ipv4.tcp_retries2的默認(rèn)值為5或者15,對(duì)應(yīng)的超時(shí)時(shí)間如下表:

tcp_retries2對(duì)端無(wú)響應(yīng)

525.6s-51.2s,根據(jù)動(dòng)態(tài)rto定

15924.6s-1044.6s,根據(jù)動(dòng)態(tài)rto定

和SYN報(bào)文的超時(shí)時(shí)間一樣,如果應(yīng)用層設(shè)置了超時(shí)時(shí)間,哪么具體的超時(shí)時(shí)間以?xún)?nèi)核和應(yīng)用層的超時(shí)時(shí)間的最小值為準(zhǔn)。

socket的write系統(tǒng)調(diào)用最后調(diào)用的是tcp_sendmsg,源碼如下所示:

int tcp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,

size_t size){

......

timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);

......

while (--iovlen >= 0) {

......

// 此種情況是buffer不夠了

if (copy <= 0) {

new_segment:

......

if (!sk_stream_memory_free(sk))

goto wait_for_sndbuf;

?

skb = sk_stream_alloc_skb(sk, select_size(sk),sk->sk_allocation);

if (!skb)

goto wait_for_memory;

}

......

}

......

// 這邊等待write buffer有空間

wait_for_sndbuf:

set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);

wait_for_memory:

if (copied)

tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);

// 這邊等待timeo長(zhǎng)的時(shí)間

if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)

goto do_error;

......

out:

// 如果拷貝了數(shù)據(jù),則返回

if (copied)

tcp_push(sk, flags, mss_now, tp->nonagle);

TCP_CHECK_TIMER(sk);

release_sock(sk);

return copied;

out_err:

// error的處理

err = sk_stream_error(sk, flags, err);

TCP_CHECK_TIMER(sk);

release_sock(sk);

return err;

}

從上面的內(nèi)核代碼看出,如果socket的write buffer依舊有空間的時(shí)候,會(huì)立馬返回,并不會(huì)有timeout。但是write buffer不夠的時(shí)候,會(huì)等待SO_SNDTIMEO的時(shí)間(nonblock時(shí)候?yàn)?)。但是如果SO_SNDTIMEO沒(méi)有設(shè)置的時(shí)候,默認(rèn)初始化為MAX_SCHEDULE_TIMEOUT,可以認(rèn)為其超時(shí)時(shí)間為無(wú)限。那么其超時(shí)時(shí)間會(huì)有另一個(gè)條件來(lái)決定,我們看下sk_stream_wait_memory的源碼:

int sk_stream_wait_memory(struct sock *sk, long *timeo_p){

// 等待socket shutdown或者socket出現(xiàn)err

sk_wait_event(sk, ¤t_timeo, sk->sk_err ||

(sk->sk_shutdown & SEND_SHUTDOWN) ||

(sk_stream_memory_free(sk) &&

!vm_wait));

}

在write等待的時(shí)候,如果出現(xiàn)socket被shutdown或者socket出現(xiàn)錯(cuò)誤的時(shí)候,則會(huì)跳出wait進(jìn)而返回錯(cuò)誤。在不考慮對(duì)端shutdown的情況下,出現(xiàn)sk_err的時(shí)間其實(shí)就是其write的timeout時(shí)間,那么我們看下什么時(shí)候出現(xiàn)sk->sk_err。

SO_SNDTIMEO不設(shè)置,write buffer滿(mǎn)之后ack一直不返回的情況(例如,物理機(jī)宕機(jī))

物理機(jī)宕機(jī)后,tcp發(fā)送msg的時(shí)候,ack不會(huì)返回,則會(huì)在重傳定時(shí)器tcp_retransmit_timer到期后timeout,其重傳到期時(shí)間通過(guò)tcp_retries2以及TCP_RTO_MIN計(jì)算出來(lái)。

tcp_retries2的設(shè)置位置為:

cat /proc/sys/net/ipv4/tcp_retries2

SO_SNDTIMEO不設(shè)置,write buffer滿(mǎn)之后對(duì)端不消費(fèi),導(dǎo)致buffer一直滿(mǎn)的情況

和上面ack超時(shí)有些許不一樣的是,一個(gè)邏輯是用TCP_RTO_MIN通過(guò)tcp_retries2計(jì)算出來(lái)的時(shí)間。另一個(gè)是真的通過(guò)重傳超過(guò)tcp_retries2次數(shù)來(lái)time_out,兩者的區(qū)別和rto的動(dòng)態(tài)計(jì)算有關(guān)。但是可以大致認(rèn)為是一致的。

上述邏輯如下圖所示:

sockettimeout,音視頻開(kāi)發(fā),websocket,網(wǎng)絡(luò),音視頻,Powered by 金山文檔

write_timeout表格

tcp_retries2

buffer未滿(mǎn)

buffer滿(mǎn)

5

立即返回

min(SO_SNDTIMEO,(25.6s-51.2s)根據(jù)動(dòng)態(tài)rto定

15

立即返回

min(SO_SNDTIMEO,(924.6s-1044.6s)根據(jù)動(dòng)態(tài)rto定

4、接收超時(shí)


在tcp協(xié)議中,讀的操作和寫(xiě)操作的邏輯是相通的。

tcp連接建立后,兩邊的通信無(wú)非就是報(bào)文的互傳。寫(xiě)操作是將數(shù)據(jù)放到tcp報(bào)文中發(fā)送給對(duì)端,然后等待對(duì)端響應(yīng),一定時(shí)間沒(méi)有得到響應(yīng)就是超時(shí)。而讀操作其實(shí)就是發(fā)送一個(gè)讀取數(shù)據(jù)的報(bào)文給對(duì)端,然后對(duì)端返回帶有數(shù)據(jù)的報(bào)文,一定時(shí)間沒(méi)有收到對(duì)端的報(bào)文則認(rèn)為超時(shí)。對(duì)于tcp協(xié)議而言,其實(shí)不會(huì)分辨他們發(fā)送的報(bào)文具體是要干嘛,因此readTimeout的判斷邏輯和writeTimeout基本一樣。它的重傳次數(shù)也是由參數(shù)net.ipv4.tcp_retries2控制。在應(yīng)用層面也一般是統(tǒng)一叫socketTimeout。

read系統(tǒng)調(diào)用

socket的read系統(tǒng)調(diào)用最終調(diào)用的是tcp_recvmsg, 其源碼如下:

int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,

size_t len, int nonblock, int flags, int *addr_len)

{

......

// 這邊timeo=SO_RCVTIMEO

timeo = sock_rcvtimeo(sk, nonblock);

......

do{

......

// 下面這一堆判斷表明,如果出現(xiàn)錯(cuò)誤,或者已經(jīng)被CLOSE/SHUTDOWN則跳出循環(huán)

if(copied) {

if (sk->sk_err ||

sk->sk_state == TCP_CLOSE ||

(sk->sk_shutdown & RCV_SHUTDOWN) ||

!timeo ||

signal_pending(current))

break;

} else {

if (sock_flag(sk, SOCK_DONE))

break;

?

if (sk->sk_err) {

copied = sock_error(sk);

break;

}

// 如果socket shudown跳出

if (sk->sk_shutdown & RCV_SHUTDOWN)

break;

// 如果socket close跳出

if (sk->sk_state == TCP_CLOSE) {

if (!sock_flag(sk, SOCK_DONE)) {

/* This occurs when user tries to read

* from never connected socket.

*/

copied = -ENOTCONN;

break;

}

break;

}

.......

}

.......

?

if (copied >= target) {

/* Do not sleep, just process backlog. */

release_sock(sk);

lock_sock(sk);

} else /* 如果沒(méi)有讀到target自己數(shù)(和水位有關(guān),可以暫認(rèn)為是1),則等待SO_RCVTIMEO的時(shí)間 */

sk_wait_data(sk, &timeo);

} while (len > 0);

......

}

上面的邏輯如下圖所示:

sockettimeout,音視頻開(kāi)發(fā),websocket,網(wǎng)絡(luò),音視頻,Powered by 金山文檔

重傳以及探測(cè)定時(shí)器timeout事件的觸發(fā)時(shí)機(jī)如下圖所示:

sockettimeout,音視頻開(kāi)發(fā),websocket,網(wǎng)絡(luò),音視頻,Powered by 金山文檔

如果內(nèi)核層面ack正常返回而且對(duì)端窗口不為0,僅僅應(yīng)用層不返回任何數(shù)據(jù),那么就會(huì)無(wú)限等待,直到對(duì)端有數(shù)據(jù)或者socket close/shutdown為止,如下圖所示:

sockettimeout,音視頻開(kāi)發(fā),websocket,網(wǎng)絡(luò),音視頻,Powered by 金山文檔

很多應(yīng)用就是基于這個(gè)無(wú)限超時(shí)來(lái)設(shè)計(jì)的,例如activemq的消費(fèi)者邏輯。

ReadTimeout超時(shí)表格

C系統(tǒng)調(diào)用:

tcp_retries2

對(duì)端無(wú)響應(yīng)

對(duì)端內(nèi)核響應(yīng)正常

5

min(SO_RCVTIMEO,(25.6s-51.2s)根據(jù)動(dòng)態(tài)rto定

SO_RCVTIMEO==0?無(wú)限,SO_RCVTIMEO)

15

min(SO_RCVTIMEO,(924.6s-1044.6s)根據(jù)動(dòng)態(tài)rto定

SO_RCVTIMEO==0?無(wú)限,SO_RCVTIMEO)

Java系統(tǒng)調(diào)用

tcp_retries2

對(duì)端無(wú)響應(yīng)

對(duì)端內(nèi)核響應(yīng)正常

5

min(SO_TIMEOUT,(25.6s-51.2s)根據(jù)動(dòng)態(tài)rto定

SO_TIMEOUT==0?無(wú)限,SO_RCVTIMEO

15

min(SO_TIMEOUT,(924.6s-1044.6s)根據(jù)動(dòng)態(tài)rto定

SO_TIMEOUT==0?無(wú)限,SO_RCVTIMEO

5、對(duì)端物理機(jī)宕機(jī)之后的超時(shí)


對(duì)端物理機(jī)宕機(jī)后還依舊有數(shù)據(jù)發(fā)送

對(duì)端物理機(jī)宕機(jī)時(shí)對(duì)端內(nèi)核也gg了(不會(huì)發(fā)出任何包通知宕機(jī)),那么本端發(fā)送任何數(shù)據(jù)給對(duì)端都不會(huì)有響應(yīng)。其超時(shí)時(shí)間就由上面討論的min(設(shè)置的socket超時(shí)[例如SO_TIMEOUT],內(nèi)核內(nèi)部的定時(shí)器超時(shí)來(lái)決定)。

對(duì)端物理機(jī)宕機(jī)后沒(méi)有數(shù)據(jù)發(fā)送,但在read等待

這時(shí)候如果設(shè)置了超時(shí)時(shí)間timeout,則在timeout后返回。但是,如果僅僅是在read等待,由于底層沒(méi)有數(shù)據(jù)交互,那么其無(wú)法知道對(duì)端是否宕機(jī),所以會(huì)一直等待。但是,內(nèi)核會(huì)在一個(gè)socket兩個(gè)小時(shí)都沒(méi)有數(shù)據(jù)交互情況下(可設(shè)置)啟動(dòng)keepalive定時(shí)器來(lái)探測(cè)對(duì)端的socket。如下圖所示:

sockettimeout,音視頻開(kāi)發(fā),websocket,網(wǎng)絡(luò),音視頻,Powered by 金山文檔

大概是2小時(shí)11分鐘之后會(huì)超時(shí)返回。keepalive的設(shè)置由內(nèi)核參數(shù)指定:

cat /proc/sys/net/ipv4/tcp_keepalive_time 7200 即兩個(gè)小時(shí)后開(kāi)始探測(cè)

cat /proc/sys/net/ipv4/tcp_keepalive_intvl 75 即每次探測(cè)間隔為75s

cat /proc/sys/net/ipv4/tcp_keepalve_probes 9 即一共探測(cè)9次

可以在setsockops中對(duì)單獨(dú)的socket指定是否啟用keepalive定時(shí)器。

對(duì)端物理機(jī)宕機(jī)后沒(méi)有數(shù)據(jù)發(fā)送,也沒(méi)有read等待

和上面同理,也是在keepalive定時(shí)器超時(shí)之后,將連接close。所以我們可以看到一個(gè)不活躍的socket在對(duì)端物理機(jī)突然宕機(jī)之后,依舊是ESTABLISHED狀態(tài),過(guò)很長(zhǎng)一段時(shí)間之后才會(huì)關(guān)閉。

6、進(jìn)程宕機(jī)后的超時(shí)


物理機(jī)突然宕機(jī)和進(jìn)程宕掉的表現(xiàn)不一樣。一個(gè)tcp連接建立后,如果一端的物理機(jī)突然宕機(jī),另外一端是完全不知情的,它會(huì)像往常一樣繼續(xù)發(fā)送相關(guān)報(bào)文,直到超時(shí)時(shí)間到了才返回。另外,一般操作系統(tǒng)會(huì)有機(jī)制檢測(cè)來(lái)釋放該tcp連接。而如果只是進(jìn)程宕掉,在進(jìn)程退出的時(shí)候,操作會(huì)負(fù)責(zé)回收這個(gè)進(jìn)程所屬的所有tcp連接,在這時(shí)會(huì)向這些tcp連接的對(duì)端發(fā)送FIN報(bào)文,表示要關(guān)閉連接了,這時(shí)候?qū)Χ耸强梢灾肋B接已經(jīng)關(guān)閉的。(如果進(jìn)程退出后還收到來(lái)自對(duì)端的報(bào)文,那么內(nèi)核會(huì)立馬發(fā)送reset給對(duì)端,從而不會(huì)卡住對(duì)端的線(xiàn)程資源)

所以如果僅僅是對(duì)端進(jìn)程宕機(jī)的話(huà)(進(jìn)程所在內(nèi)核會(huì)close其所擁有的所有socket),由于fin包的發(fā)送,本端內(nèi)核可以立刻知道當(dāng)前socket的狀態(tài)。如果socket是阻塞的,那么將會(huì)在當(dāng)前或者下一次write/read系統(tǒng)調(diào)用的時(shí)候返回給應(yīng)用層相應(yīng)的錯(cuò)誤。如果是nonblock,那么會(huì)在select/epoll中觸發(fā)出對(duì)應(yīng)的事件通知應(yīng)用層去處理。如果fin包沒(méi)發(fā)送到對(duì)端,那么在下一次write/read的時(shí)候內(nèi)核會(huì)發(fā)送reset包作為回應(yīng)。

nonblock

設(shè)置為nonblock=true后,由于read/write都是立刻返回,且通過(guò)select/epoll等處理重傳超時(shí)/probe超時(shí)/keep alive超時(shí)/socket close等事件,所以根據(jù)應(yīng)用層代碼決定其超時(shí)特性。定時(shí)器超時(shí)事件發(fā)生的時(shí)間如上面幾小節(jié)所述,和是否nonblock無(wú)關(guān)。nonblock的編程模式可以讓?xiě)?yīng)用層對(duì)這些事件做出響應(yīng)。

7、總結(jié)


網(wǎng)絡(luò)編程中超時(shí)時(shí)間是個(gè)重要但又容易被忽略的問(wèn)題,這個(gè)問(wèn)題只有在遇到物理機(jī)宕機(jī),偶爾的網(wǎng)絡(luò)抖動(dòng)等平時(shí)遇不到的現(xiàn)象時(shí)候才會(huì)凸顯。希望本篇文章可以對(duì)讀者在以后遇到類(lèi)似超時(shí)問(wèn)題時(shí)有所幫助,只要涉及到阻塞式的網(wǎng)絡(luò)請(qǐng)求,就一定要加超時(shí),否則你將進(jìn)入自己曾經(jīng)種下的苦果,加班,掉的不是汗水,是頭發(fā)。

原文https://zhuanlan.zhihu.com/p/535405145

★文末名片可以免費(fèi)領(lǐng)取音視頻開(kāi)發(fā)學(xué)習(xí)資料,內(nèi)容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音視頻學(xué)習(xí)路線(xiàn)圖等等。

見(jiàn)下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-663138.html

到了這里,關(guān)于深入剖析阻塞式socket的timeout的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 深入探究音視頻開(kāi)源庫(kù)WebRTC中NetEQ音頻抗網(wǎng)絡(luò)延時(shí)與抗丟包的實(shí)現(xiàn)機(jī)制

    深入探究音視頻開(kāi)源庫(kù)WebRTC中NetEQ音頻抗網(wǎng)絡(luò)延時(shí)與抗丟包的實(shí)現(xiàn)機(jī)制

    目錄 1、引言 2、WebRTC簡(jiǎn)介 3、什么是NetEQ? 4、NetEQ技術(shù)詳解 4.1、NetEQ概述 4.2、抖動(dòng)消除技術(shù) 4.3、丟包補(bǔ)償技術(shù) 4.4、NetEQ概要設(shè)計(jì) 4.5、NetEQ的命令機(jī)制 4.6、NetEQ的播放機(jī)制 4.7、MCU的控制機(jī)制 4.8、DSP的算法處理 4.9、DSP算法的模擬測(cè)試 5、NetEQ源文件說(shuō)明 6、參考文檔 C++軟件異常

    2024年04月25日
    瀏覽(18)
  • 深入探究音視頻開(kāi)源庫(kù) WebRTC 中 NetEQ 音頻抗網(wǎng)絡(luò)延時(shí)與抗丟包的實(shí)現(xiàn)機(jī)制

    記錄日常工作中遇到的音視頻問(wèn)題,以供大家借鑒或參考!

    2024年02月08日
    瀏覽(20)
  • socket 的阻塞模式和非阻塞模式

    socket 的阻塞模式和非阻塞模式

    對(duì) socket 在阻塞和非阻塞模式下的各個(gè)函數(shù)的行為差別深入的理解是掌握網(wǎng)絡(luò)編程的基本要求之一,是重點(diǎn)也是難點(diǎn)。 阻塞和非阻塞模式下,我們常討論的具有不同行為表現(xiàn)的 socket 函數(shù)一般有如下幾個(gè),見(jiàn)下表: connect accept send (Linux 平臺(tái)上對(duì) socket 進(jìn)行操作時(shí)也包括 write 函

    2024年02月04日
    瀏覽(20)
  • 音視頻學(xué)習(xí)-音視頻基礎(chǔ)

    音視頻學(xué)習(xí)-音視頻基礎(chǔ)

    ` ? 像素:像素是一個(gè)圖片的基本單位,pix是英語(yǔ)單詞picture的簡(jiǎn)寫(xiě),加上英語(yǔ)單詞“元素element”,就得到了“pixel”,簡(jiǎn)稱(chēng)px,所以“像素”有“圖像元素”之意。 ? 分辨率:是指圖像的大小或尺寸。比如1920x1080。 ? 位深:是指在記錄數(shù)字圖像的顏色時(shí),計(jì)算機(jī)實(shí)際上是用

    2024年02月12日
    瀏覽(169)
  • ffmpeg@音視頻工具@音視頻合并

    FFmpeg中文網(wǎng) (github.net.cn) FFmpeg 是一款強(qiáng)大的開(kāi)源跨平臺(tái)音視頻處理工具集,它包含了一系列命令行工具以及用于音頻和視頻編碼解碼、格式轉(zhuǎn)換、抓取、流化等功能的庫(kù)。FFmpeg 支持多種視頻、音頻格式和編解碼器,能夠進(jìn)行音視頻的壓縮、封裝、轉(zhuǎn)碼、分割、合并、過(guò)濾、抓

    2024年03月17日
    瀏覽(29)
  • 音視頻學(xué)習(xí)—音視頻理論基礎(chǔ)(2)

    音視頻學(xué)習(xí)—音視頻理論基礎(chǔ)(2)

    ??音頻是一種模擬信號(hào),它是由聲波轉(zhuǎn)化而來(lái)的電信號(hào)。聲波是通過(guò)氣體、液體或固體傳播的機(jī)械波,代表了聲音的震動(dòng)。在錄制過(guò)程中,聲音被轉(zhuǎn)換成電信號(hào),然后被儲(chǔ)存在數(shù)字格式中。 ??聲音的三要素是頻率、振幅和波形 ??頻率是指聲波的振動(dòng)次數(shù),通常使用赫

    2024年04月29日
    瀏覽(33)
  • 音視頻 FFmpeg音視頻處理流程

    音視頻 FFmpeg音視頻處理流程

    推薦一個(gè)零聲學(xué)院項(xiàng)目課,個(gè)人覺(jué)得老師講得不錯(cuò),分享給大家: 零聲白金學(xué)習(xí)卡(含基礎(chǔ)架構(gòu)/高性能存儲(chǔ)/golang云原生/音視頻/Linux內(nèi)核) https://xxetb.xet.tech/s/VsFMs

    2024年02月12日
    瀏覽(97)
  • 【音視頻】ffplay解析-音視頻同步

    主要解析:以音頻為基準(zhǔn),讓視頻同步音頻 思路 視頻慢了則丟掉部分視頻幀(視覺(jué)-畫(huà)?跳幀) 視頻快了則繼續(xù)渲染上?幀 具體實(shí)現(xiàn) ffplay具體源碼

    2024年02月07日
    瀏覽(30)
  • 音視頻 ffmpeg命令提取音視頻數(shù)據(jù)

    保留封裝格式 提取視頻 提取音頻 推薦一個(gè)零聲學(xué)院項(xiàng)目課,個(gè)人覺(jué)得老師講得不錯(cuò),分享給大家: 零聲白金學(xué)習(xí)卡(含基礎(chǔ)架構(gòu)/高性能存儲(chǔ)/golang云原生/音視頻/Linux內(nèi)核) https://xxetb.xet.tech/s/VsFMs

    2024年02月10日
    瀏覽(26)
  • linux 音視頻架構(gòu) linux音視頻開(kāi)發(fā)

    轉(zhuǎn)載 mob6454cc65110a 2023-07-26 22:27:01 文章標(biāo)簽 linux 音視頻架構(gòu) ci QT 視頻教程 文章分類(lèi) 架構(gòu) 后端開(kāi)發(fā) 閱讀數(shù) 117 目錄 前言 1、軟件工具準(zhǔn)備 a. 錄音軟件 b. 錄屏軟件 c. 攝像頭軟件 d. 安卓屏幕操作軟件 e. 視頻剪輯軟件

    2024年02月07日
    瀏覽(30)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包