自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

被微信面麻了,問(wèn)的太細(xì)節(jié)了。。。

開(kāi)發(fā) 前端
上周有個(gè)讀者在面試微信的時(shí)候,被問(wèn)到既然打開(kāi) net.ipv4.tcp_tw_reuse 參數(shù)可以快速?gòu)?fù)用處于 TIME_WAIT 狀態(tài)的 TCP 連接,那為什么 Linux 默認(rèn)是關(guān)閉狀態(tài)呢?

[[442111]]

大家好,我是小林。

上周有個(gè)讀者在面試微信的時(shí)候,被問(wèn)到既然打開(kāi) net.ipv4.tcp_tw_reuse 參數(shù)可以快速?gòu)?fù)用處于 TIME_WAIT 狀態(tài)的 TCP 連接,那為什么 Linux 默認(rèn)是關(guān)閉狀態(tài)呢?

好家伙,真的問(wèn)好細(xì)節(jié)!

當(dāng)時(shí)看到讀者這個(gè)問(wèn)題的時(shí)候,我也是一臉懵逼的,經(jīng)過(guò)我的一番思考后,終于知道怎么回答這題了。

其實(shí)這題在變相問(wèn)「如果 TIME_WAIT 狀態(tài)持續(xù)時(shí)間過(guò)短或者沒(méi)有,會(huì)有什么問(wèn)題?」

因?yàn)殚_(kāi)啟 tcp_tw_reuse 參數(shù)可以快速?gòu)?fù)用處于 TIME_WAIT 狀態(tài)的 TCP 連接時(shí),相當(dāng)于縮短了 TIME_WAIT 狀態(tài)的持續(xù)時(shí)間。

可能有的同學(xué)會(huì)問(wèn)說(shuō),使用 tcp_tw_reuse 快速?gòu)?fù)用處于 TIME_WAIT 狀態(tài)的 TCP 連接時(shí),是需要保證 net.ipv4.tcp_timestamps 參數(shù)是開(kāi)啟的(默認(rèn)是開(kāi)啟的),而 tcp_timestamps 參數(shù)可以避免舊連接的延遲報(bào)文,這不是解決了沒(méi)有 TIME_WAIT 狀態(tài)時(shí)的問(wèn)題了嗎?

是解決部分問(wèn)題,但是不能完全解決,接下來(lái),我跟大家聊聊這個(gè)問(wèn)題。

什么是 TIME_WAIT 狀態(tài)?

TCP 四次揮手過(guò)程,如下圖:

  • 客戶端打算關(guān)閉連接,此時(shí)會(huì)發(fā)送一個(gè) TCP 首部 FIN 標(biāo)志位被置為 1 的報(bào)文,也即 FIN 報(bào)文,之后客戶端進(jìn)入 FIN_WAIT_1 狀態(tài)。
  • 服務(wù)端收到該報(bào)文后,就向客戶端發(fā)送 ACK 應(yīng)答報(bào)文,接著服務(wù)端進(jìn)入 CLOSED_WAIT 狀態(tài)。
  • 客戶端收到服務(wù)端的 ACK 應(yīng)答報(bào)文后,之后進(jìn)入 FIN_WAIT_2 狀態(tài)。
  • 等待服務(wù)端處理完數(shù)據(jù)后,也向客戶端發(fā)送 FIN 報(bào)文,之后服務(wù)端進(jìn)入 LAST_ACK 狀態(tài)。
  • 客戶端收到服務(wù)端的 FIN 報(bào)文后,回一個(gè) ACK 應(yīng)答報(bào)文,之后進(jìn)入 TIME_WAIT 狀態(tài)
  • 服務(wù)器收到了 ACK 應(yīng)答報(bào)文后,就進(jìn)入了 CLOSE 狀態(tài),至此服務(wù)端已經(jīng)完成連接的關(guān)閉。
  • 客戶端在經(jīng)過(guò) 2MSL 一段時(shí)間后,自動(dòng)進(jìn)入 CLOSE 狀態(tài),至此客戶端也完成連接的關(guān)閉。

你可以看到,兩個(gè)方向都需要一個(gè) FIN 和一個(gè) ACK,因此通常被稱為四次揮手。

這里一點(diǎn)需要注意是:主動(dòng)關(guān)閉連接的,才有 TIME_WAIT 狀態(tài)。

可以看到,TIME_WAIT 是「主動(dòng)關(guān)閉方」斷開(kāi)連接時(shí)的最后一個(gè)狀態(tài),該狀態(tài)會(huì)持續(xù) 2MSL(Maximum Segment Lifetime) 時(shí)長(zhǎng),之后進(jìn)入CLOSED 狀態(tài)。

MSL 指的是 TCP 協(xié)議中任何報(bào)文在網(wǎng)絡(luò)上最大的生存時(shí)間,任何超過(guò)這個(gè)時(shí)間的數(shù)據(jù)都將被丟棄。雖然 RFC 793 規(guī)定 MSL 為 2 分鐘,但是在實(shí)際實(shí)現(xiàn)的時(shí)候會(huì)有所不同,比如 Linux 默認(rèn)為 30 秒,那么 2MSL 就是 60 秒。

MSL 是由網(wǎng)絡(luò)層的 IP 包中的 TTL 來(lái)保證的,TTL 是 IP 頭部的一個(gè)字段,用于設(shè)置一個(gè)數(shù)據(jù)報(bào)可經(jīng)過(guò)的路由器的數(shù)量上限。報(bào)文每經(jīng)過(guò)一次路由器的轉(zhuǎn)發(fā),IP 頭部的 TTL 字段就會(huì)減 1,減到 0 時(shí)報(bào)文就被丟棄。

MSL 與 TTL 的區(qū)別:MSL 的單位是時(shí)間,而 TTL 是經(jīng)過(guò)路由跳數(shù)。所以 MSL 應(yīng)該要大于等于 TTL 消耗為 0 的時(shí)間,以確保報(bào)文已被自然消亡。

TTL 的值一般是 64,Linux 將 MSL 設(shè)置為 30 秒,意味著 Linux 認(rèn)為數(shù)據(jù)報(bào)文經(jīng)過(guò) 64 個(gè)路由器的時(shí)間不會(huì)超過(guò) 30 秒,如果超過(guò)了,就認(rèn)為報(bào)文已經(jīng)消失在網(wǎng)絡(luò)中了。

為什么要設(shè)計(jì) TIME_WAIT 狀態(tài)?

設(shè)計(jì) TIME_WAIT 狀態(tài),主要有兩個(gè)原因:

  • 防止歷史連接中的數(shù)據(jù),被后面相同四元組的連接錯(cuò)誤的接收;
  • 保證「被動(dòng)關(guān)閉連接」的一方,能被正確的關(guān)閉;

原因一:防止歷史連接中的數(shù)據(jù),被后面相同四元組的連接錯(cuò)誤的接收

為了能更好的理解這個(gè)原因,我們先來(lái)了解序列號(hào)(SEQ)和初始序列號(hào)(ISN)。

  • 序列號(hào),是 TCP 一個(gè)頭部字段,標(biāo)識(shí)了 TCP 發(fā)送端到 TCP 接收端的數(shù)據(jù)流的一個(gè)字節(jié),因?yàn)?TCP 是面向字節(jié)流的可靠協(xié)議,為了保證消息的順序性和可靠性,TCP 為每個(gè)傳輸方向上的每個(gè)字節(jié)都賦予了一個(gè)編號(hào),以便于傳輸成功后確認(rèn)、丟失后重傳以及在接收端保證不會(huì)亂序。序列號(hào)是一個(gè) 32 位的無(wú)符號(hào)數(shù),因此在到達(dá) 4G 之后再循環(huán)回到 0。
  • 初始序列號(hào),在 TCP 建立連接的時(shí)候,客戶端和服務(wù)端都會(huì)各自生成一個(gè)初始序列號(hào),它是基于時(shí)鐘生成的一個(gè)隨機(jī)數(shù),來(lái)保證每個(gè)連接都擁有不同的初始序列號(hào)。初始化序列號(hào)可被視為一個(gè) 32 位的計(jì)數(shù)器,該計(jì)數(shù)器的數(shù)值每 4 微秒加 1,循環(huán)一次需要 4.55 小時(shí)。

給大家抓了一個(gè)包,下圖中的 Seq 就是序列號(hào),其中紅色框住的分別是客戶端和服務(wù)端各自生成的初始序列號(hào)。

通過(guò)前面我們知道,序列號(hào)和初始化序列號(hào)并不是無(wú)限遞增的,會(huì)發(fā)生回繞為初始值的情況,這意味著無(wú)法根據(jù)序列號(hào)來(lái)判斷新老數(shù)據(jù)。

假設(shè) TIME-WAIT 沒(méi)有等待時(shí)間或時(shí)間過(guò)短,被延遲的數(shù)據(jù)包抵達(dá)后會(huì)發(fā)生什么呢?

  • 服務(wù)端在關(guān)閉連接之前發(fā)送的 SEQ = 301 報(bào)文,被網(wǎng)絡(luò)延遲了。
  • 接著,服務(wù)端以相同的四元組重新打開(kāi)了新連接,前面被延遲的 SEQ = 301 這時(shí)抵達(dá)了客戶端,而且該數(shù)據(jù)報(bào)文的序列號(hào)剛好在客戶端接收窗口內(nèi),因此客戶端會(huì)正常接收這個(gè)數(shù)據(jù)報(bào)文,但是這個(gè)數(shù)據(jù)報(bào)文是上一個(gè)連接殘留下來(lái)的,這樣就產(chǎn)生數(shù)據(jù)錯(cuò)亂等嚴(yán)重的問(wèn)題。

為了防止歷史連接中的數(shù)據(jù),被后面相同四元組的連接錯(cuò)誤的接收,因此 TCP 設(shè)計(jì)了 TIME_WAIT 狀態(tài),狀態(tài)會(huì)持續(xù) 2MSL 時(shí)長(zhǎng),這個(gè)時(shí)間足以讓兩個(gè)方向上的數(shù)據(jù)包都被丟棄,使得原來(lái)連接的數(shù)據(jù)包在網(wǎng)絡(luò)中都自然消失,再出現(xiàn)的數(shù)據(jù)包一定都是新建立連接所產(chǎn)生的。

原因二:保證「被動(dòng)關(guān)閉連接」的一方,能被正確的關(guān)閉

如果客戶端(主動(dòng)關(guān)閉方)最后一次 ACK 報(bào)文(第四次揮手)在網(wǎng)絡(luò)中丟失了,那么按照 TCP 可靠性原則,服務(wù)端(被動(dòng)關(guān)閉方)會(huì)重發(fā) FIN 報(bào)文。

假設(shè)客戶端沒(méi)有 TIME_WAIT 狀態(tài),而是在發(fā)完最后一次回 ACK 報(bào)文就直接進(jìn)入 CLOSED 狀態(tài),如果該 ACK 報(bào)文丟失了,服務(wù)端則重傳的 FIN 報(bào)文,而這時(shí)客戶端已經(jīng)進(jìn)入到關(guān)閉狀態(tài)了,在收到服務(wù)端重傳的 FIN 報(bào)文后,就會(huì)回 RST 報(bào)文。

服務(wù)端收到這個(gè) RST 并將其解釋為一個(gè)錯(cuò)誤(Connection reset by peer),這對(duì)于一個(gè)可靠的協(xié)議來(lái)說(shuō)不是一個(gè)優(yōu)雅的終止方式。

為了防止這種情況出現(xiàn),客戶端必須等待足夠長(zhǎng)的時(shí)間確保對(duì)端收到 ACK,如果對(duì)端沒(méi)有收到 ACK,那么就會(huì)觸發(fā) TCP 重傳機(jī)制,服務(wù)端會(huì)重新發(fā)送一個(gè) FIN,這樣一去一來(lái)剛好兩個(gè) MSL 的時(shí)間。

但是你可能會(huì)說(shuō)重新發(fā)送的 ACK 還是有可能丟失啊,沒(méi)錯(cuò),但 TCP 已經(jīng)等待了那么長(zhǎng)的時(shí)間了,已經(jīng)算仁至義盡了。

tcp_tw_reuse 是什么?

在 Linux 操作系統(tǒng)下,TIME_WAIT 狀態(tài)的持續(xù)時(shí)間是 60 秒,這意味著這 60 秒內(nèi),客戶端一直會(huì)占用著這個(gè)端口。要知道,端口資源也是有限的,一般可以開(kāi)啟的端口為 32768~61000 ,也可以通過(guò)如下參數(shù)設(shè)置指定范圍:

  1. net.ipv4.ip_local_port_range 

那么,如果如果主動(dòng)關(guān)閉連接方的 TIME_WAIT 狀態(tài)過(guò)多,占滿了所有端口資源,則會(huì)導(dǎo)致無(wú)法創(chuàng)建新連接。

不過(guò),Linux 操作系統(tǒng)提供了兩個(gè)可以系統(tǒng)參數(shù)來(lái)快速回收處于 TIME_WAIT 狀態(tài)的連接,這兩個(gè)參數(shù)都是默認(rèn)關(guān)閉的:

  • net.ipv4.tcp_tw_reuse,如果開(kāi)啟該選項(xiàng)的話,客戶端(連接發(fā)起方) 在調(diào)用 connect() 函數(shù)時(shí),內(nèi)核會(huì)隨機(jī)找一個(gè) TIME_WAIT 狀態(tài)超過(guò) 1 秒的連接給新的連接復(fù)用,所以該選項(xiàng)只適用于連接發(fā)起方。
  • net.ipv4.tcp_tw_recycle,如果開(kāi)啟該選項(xiàng)的話,允許處于 TIME_WAIT 狀態(tài)的連接被快速回收,該參數(shù)在 NAT 的網(wǎng)絡(luò)下是不安全的!詳細(xì)見(jiàn)這篇文章介紹:字節(jié)面試:SYN 報(bào)文什么時(shí)候情況下會(huì)被丟棄?

要使得上面這兩個(gè)參數(shù)生效,有一個(gè)前提條件,就是要打開(kāi) TCP 時(shí)間戳,即 net.ipv4.tcp_timestamps=1(默認(rèn)即為 1)。

開(kāi)啟了 tcp_timestamps 參數(shù),TCP 頭部就會(huì)使用時(shí)間戳選項(xiàng),它有兩個(gè)好處,一個(gè)是便于精確計(jì)算 RTT ,另一個(gè)是能防止序列號(hào)回繞(PAWS),我們先來(lái)介紹這個(gè)功能。

序列號(hào)是一個(gè) 32 位的無(wú)符號(hào)整型,上限值是 4GB,超過(guò) 4GB 后就需要將序列號(hào)回繞進(jìn)行重用。這在以前網(wǎng)速慢的年代不會(huì)造成什么問(wèn)題,但在一個(gè)速度足夠快的網(wǎng)絡(luò)中傳輸大量數(shù)據(jù)時(shí),序列號(hào)的回繞時(shí)間就會(huì)變短。如果序列號(hào)回繞的時(shí)間極短,我們就會(huì)再次面臨之前延遲的報(bào)文抵達(dá)后序列號(hào)依然有效的問(wèn)題。

為了解決這個(gè)問(wèn)題,就需要有 TCP 時(shí)間戳。

試看下面的示例,假設(shè) TCP 的發(fā)送窗口是 1 GB,并且使用了時(shí)間戳選項(xiàng),發(fā)送方會(huì)為每個(gè) TCP 報(bào)文分配時(shí)間戳數(shù)值,我們假設(shè)每個(gè)報(bào)文時(shí)間加 1,然后使用這個(gè)連接傳輸一個(gè) 6GB 大小的數(shù)據(jù)流。

32 位的序列號(hào)在時(shí)刻 D 和 E 之間回繞。假設(shè)在時(shí)刻B有一個(gè)報(bào)文丟失并被重傳,又假設(shè)這個(gè)報(bào)文段在網(wǎng)絡(luò)上繞了遠(yuǎn)路并在時(shí)刻 F 重新出現(xiàn)。如果 TCP 無(wú)法識(shí)別這個(gè)繞回的報(bào)文,那么數(shù)據(jù)完整性就會(huì)遭到破壞。

使用時(shí)間戳選項(xiàng)能夠有效的防止上述問(wèn)題,如果丟失的報(bào)文會(huì)在時(shí)刻 F 重新出現(xiàn),由于它的時(shí)間戳為 2,小于最近的有效時(shí)間戳(5 或 6),因此防回繞序列號(hào)算法(PAWS)會(huì)將其丟棄。

防回繞序列號(hào)算法要求連接雙方維護(hù)最近一次收到的數(shù)據(jù)包的時(shí)間戳(Recent TSval),每收到一個(gè)新數(shù)據(jù)包都會(huì)讀取數(shù)據(jù)包中的時(shí)間戳值跟 Recent TSval 值做比較,如果發(fā)現(xiàn)收到的數(shù)據(jù)包中時(shí)間戳不是遞增的,則表示該數(shù)據(jù)包是過(guò)期的,就會(huì)直接丟棄這個(gè)數(shù)據(jù)包。

為什么 tcp_tw_reuse 默認(rèn)是關(guān)閉的?

通過(guò)前面這么多鋪墊,終于可以說(shuō)這個(gè)問(wèn)題了。

開(kāi)啟 tcp_tw_reuse 會(huì)有什么風(fēng)險(xiǎn)呢?我覺(jué)得會(huì)有 2 個(gè)問(wèn)題。

第一個(gè)問(wèn)題

我們知道開(kāi)啟 tcp_tw_reuse 的同時(shí),也需要開(kāi)啟 tcp_timestamps,意味著可以用時(shí)間戳的方式有效的判斷回繞序列號(hào)的歷史報(bào)文。

但是在看我看了防回繞序列號(hào)算法的源碼后,發(fā)現(xiàn)對(duì)于 RST 報(bào)文的時(shí)間戳即使過(guò)期了,只要 RST 報(bào)文的序列號(hào)在對(duì)方的接收窗口內(nèi),也是能被接受的。

下面 tcp_validate_incoming 函數(shù)就是驗(yàn)證接收到的 TCP 報(bào)文是否合格的函數(shù),其中第一步就會(huì)進(jìn)行 PAWS 檢查,由 tcp_paws_discard 函數(shù)負(fù)責(zé)。

  1. static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, const struct tcphdr *th, int syn_inerr) 
  2.     struct tcp_sock *tp = tcp_sk(sk); 
  3.  
  4.     /* RFC1323: H1. Apply PAWS check first. */ 
  5.     if (tcp_fast_parse_options(sock_net(sk), skb, th, tp) && 
  6.         tp->rx_opt.saw_tstamp && 
  7.         tcp_paws_discard(sk, skb)) { 
  8.         if (!th->rst) { 
  9.             .... 
  10.             goto discard; 
  11.         } 
  12.         /* Reset is accepted even if it did not pass PAWS. */ 
  13.     } 

當(dāng) tcp_paws_discard 返回 true,就代表報(bào)文是一個(gè)歷史報(bào)文,于是就要丟棄這個(gè)報(bào)文。但是在丟掉這個(gè)報(bào)文的時(shí)候,會(huì)先判斷是不是 RST 報(bào)文,如果不是 RST 報(bào)文,才會(huì)將報(bào)文丟掉。也就是說(shuō),即使 RST 報(bào)文是一個(gè)歷史報(bào)文,并不會(huì)被丟棄。

假設(shè)有這樣的場(chǎng)景,如下圖:

  • 客戶端向一個(gè)還沒(méi)有被服務(wù)端監(jiān)聽(tīng)的端口發(fā)起了 HTTP 請(qǐng)求,接著服務(wù)端就會(huì)回 RST 報(bào)文給對(duì)方,很可惜的是 RST 報(bào)文被網(wǎng)絡(luò)阻塞了。
  • 由于客戶端遲遲沒(méi)有收到 TCP 第二次握手,于是重發(fā)了 SYN 包,與此同時(shí)服務(wù)端已經(jīng)開(kāi)啟了服務(wù),監(jiān)聽(tīng)了對(duì)應(yīng)的端口。于是接下來(lái),客戶端和服務(wù)端就進(jìn)行了 TCP 三次握手、數(shù)據(jù)傳輸(HTTP應(yīng)答-響應(yīng))、四次揮手。
  • 因?yàn)榭蛻舳碎_(kāi)啟了 tcp_tw_reuse,于是快速?gòu)?fù)用 TIME_WAIT 狀態(tài)的端口,又與服務(wù)端建立了一個(gè)與剛才相同的四元組的連接。
  • 接著,前面被網(wǎng)絡(luò)延遲 RST 報(bào)文這時(shí)抵達(dá)了客戶端,而且 RST 報(bào)文的序列號(hào)在客戶端的接收窗口內(nèi),由于防回繞序列號(hào)算法不會(huì)防止過(guò)期的 RST,所以 RST 報(bào)文會(huì)被客戶端接受了,于是客戶端的連接就斷開(kāi)了。

上面這個(gè)場(chǎng)景就是開(kāi)啟 tcp_tw_reuse 風(fēng)險(xiǎn),因?yàn)榭焖購(gòu)?fù)用 TIME_WAIT 狀態(tài)的端口,導(dǎo)致新連接可能被回繞序列號(hào)的 RST 報(bào)文斷開(kāi)了,而如果不跳過(guò) TIME_WAIT 狀態(tài),而是停留 2MSL 時(shí)長(zhǎng),那么這個(gè) RST 報(bào)文就不會(huì)出現(xiàn)下一個(gè)新的連接。

可能大家會(huì)有這樣的疑問(wèn),為什么 PAWS 檢查要放過(guò)過(guò)期的 RST 報(bào)文。我翻了 RFC 1323 ,里面有一句提到:

It is recommended that RST segments NOT carry timestamps, and that RST segments be acceptable regardless of their timestamp. Old duplicate RST segments should be exceedingly unlikely, and their cleanup function should take precedence over timestamps.

大概的意思:建議 RST 段不攜帶時(shí)間戳,并且無(wú)論其時(shí)間戳如何,RST 段都是可接受的。老的重復(fù)的 RST 段應(yīng)該是極不可能的,并且它們的清除功能應(yīng)優(yōu)先于時(shí)間戳。

RFC 1323 提到說(shuō)收歷史的 RST 報(bào)文是極不可能,之所以有這樣的想法是因?yàn)?TIME_WAIT 狀態(tài)持續(xù)的 2MSL 時(shí)間,足以讓連接中的報(bào)文在網(wǎng)絡(luò)中自然消失,所以認(rèn)為按正常操作來(lái)說(shuō)是不會(huì)發(fā)生的,因此認(rèn)為清除連接優(yōu)先于時(shí)間戳。

而我前面提到的案例,是因?yàn)殚_(kāi)啟了 tcp_tw_reuse 狀態(tài),跳過(guò)了 TIME_WAIT 狀態(tài),才發(fā)生的事情。

有同學(xué)會(huì)說(shuō),都經(jīng)過(guò)一個(gè) HTTP 請(qǐng)求了,延遲的 RST 報(bào)文竟然還會(huì)存活?

一個(gè) HTTP 請(qǐng)求其實(shí)很快的,比如我下面這個(gè)抓包,只需要 0.2 秒就完成了,遠(yuǎn)小于 MSL,所以延遲的 RST 報(bào)文存活是有可能的。

第二個(gè)問(wèn)題

開(kāi)啟 tcp_tw_reuse 來(lái)快速?gòu)?fù)用 TIME_WAIT 狀態(tài)的連接,如果第四次揮手的 ACK 報(bào)文丟失了,有可能會(huì)導(dǎo)致被動(dòng)關(guān)閉連接的一方不能被正常的關(guān)閉,如下圖:

總結(jié)

tcp_tw_reuse 的作用是讓客戶端快速?gòu)?fù)用處于 TIME_WAIT 狀態(tài)的端口,相當(dāng)于跳過(guò)了 TIME_WAIT 狀態(tài),這可能會(huì)出現(xiàn)這樣的兩個(gè)問(wèn)題:

  • 歷史 RST 報(bào)文可能會(huì)終止后面相同四元組的連接,因?yàn)?PAWS 檢查到即使 RST 是過(guò)期的,也不會(huì)丟棄。
  • 如果第四次揮手的 ACK 報(bào)文丟失了,有可能被動(dòng)關(guān)閉連接的一方不能被正常的關(guān)閉;

雖然 TIME_WAIT 狀態(tài)持續(xù)的時(shí)間是有一點(diǎn)長(zhǎng),顯得很不友好,但是它被設(shè)計(jì)來(lái)就是用來(lái)避免發(fā)生亂七八糟的事情。

 

《UNIX網(wǎng)絡(luò)編程》一書(shū)中卻說(shuō)道:TIME_WAIT 是我們的朋友,它是有助于我們的,不要試圖避免這個(gè)狀態(tài),而是應(yīng)該弄清楚它。

 

責(zé)任編輯:武曉燕 來(lái)源: 小林coding
相關(guān)推薦

2023-09-26 08:36:31

ES6 模塊JS 題目

2023-11-03 08:10:49

ThreadLoca內(nèi)存泄露

2023-11-21 20:28:02

C++Pythonweb開(kāi)發(fā)

2020-10-13 16:30:31

語(yǔ)言鏈表數(shù)組

2023-12-18 08:03:56

并發(fā)編程Java

2025-03-28 08:53:51

2013-07-03 09:40:04

微信

2020-08-18 16:12:02

蘋果微信軟件

2021-05-14 07:18:07

監(jiān)控微信聊天

2021-06-27 06:28:55

微信微信派微信官網(wǎng)改版

2021-09-27 05:27:21

微信微信狀態(tài)騰訊

2024-01-15 07:05:50

開(kāi)發(fā)大事務(wù)數(shù)據(jù)庫(kù)

2021-09-27 22:34:14

微信廣告監(jiān)控

2019-12-27 13:31:33

Talking DatAI人工智能

2024-06-18 08:31:33

2021-02-01 12:20:35

CyclicBarri工具面試

2021-01-19 19:06:00

微信企業(yè)微信騰訊

2019-09-25 08:26:20

Python微信頭像

2013-06-20 11:11:00

程序員經(jīng)理

2021-01-22 09:56:50

微信微信8.0移動(dòng)應(yīng)用
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)