tcp特點+TCP的狀態轉換圖+time_wait詳解

tcp特點+TCP的狀態轉換圖+time wait詳解

目錄

一、tcp特點解釋

1.1 面向連接

1.1.1 連接建立——三次握手

1.1.2 連接釋放——四次揮手

1.2 可靠的

1.2.1 應答確認

1.2.2 超時重傳

1.2.3 亂序重排

1.2.4 去重

1.2.5 滑動窗口進行流量控制

1.3 流失服務(字節流傳輸)

1.3.1 tcp粘包概念

1.3.2?產生 TCP 粘包的原因

發送端原因

接收端原因

1.3.3?解決 TCP 粘包的方法

定長協議

分隔符協議

消息頭 + 消息體協議

二、服務器接收多個客戶端?

三、TCP(傳輸控制協議)的狀態轉換圖

2.1 狀態

2.2 轉換


一、tcp特點解釋

1.1 面向連接

1.1.1 連接建立——三次握手

在進行數據傳輸之前,TCP 需要通過 “三次握手” 來建立連接。具體過程為:客戶端向服務器發送一個 SYN 包,請求建立連接;服務器收到 SYN 包后,向客戶端發送一個 SYN + ACK 包,表示同意建立連接;客戶端收到 SYN + ACK 包后,再向服務器發送一個 ACK 包,連接建立完成。這種方式確保了雙方都有發送和接收數據的能力,并且雙方對連接的初始序列號達成一致。

1.1.2 連接釋放——四次揮手

數據傳輸結束后,TCP 使用 “四次揮手” 來釋放連接。客戶端發送一個 FIN 包,表示請求關閉連接;服務器收到 FIN 包后,發送一個 ACK 包表示同意關閉;接著服務器發送一個 FIN 包,表示自己也請求關閉連接;客戶端收到 FIN 包后,發送一個 ACK 包表示同意關閉,連接釋放完成。這種機制保證了雙方都能正確地結束數據傳輸。

1.2 可靠的

1.2.1 應答確認

TCP 使用確認機制來確保數據的可靠傳輸。發送方發送數據后,會等待接收方的確認信息(ACK)。如果在一定時間內沒有收到確認信息,發送方會重新發送該數據。例如,發送方發送了一個數據包,接收方收到后會返回一個帶有確認號的 ACK 包,告知發送方已經正確接收了哪些數據。

1.2.2 超時重傳

當發送方發送的數據丟失或者接收方返回的確認信息丟失時,發送方會在超時后重傳數據。TCP 通過設置定時器來實現超時重傳,定時器的時間會根據網絡狀況動態調整。

1.2.3 亂序重排

我們每發一個tcp報文都有相應的序號。TCP 保證字節流中的數據按照發送的順序到達接收方。如果數據在傳輸過程中出現亂序,TCP 會在接收方進行重新排序,確保應用層接收到的數據是有序的

1.2.4 去重

倆個相同序號的報文去重

1.2.5 滑動窗口進行流量控制

滑動窗口用于控制數據的發送速率和流量,同時保證數據的可靠傳輸。發送方和接收方都有一個滑動窗口,窗口的大小表示可以發送或接收的數據量。滑動窗口越大代表我能發送的數據越大.發送方在發送數據時,會根據接收方的窗口大小來決定發送多少數據,避免接收方緩沖區溢出。窗口內的允許發送,窗口外的不允許發送

(不會丟包因為是可靠的,底層可能會丟但是會重傳時間特別快,我們應用層感受不到)

1.3 流失服務(字節流傳輸)

多線程并發——給一個服務器同時鏈接倆個以上客戶端

發送緩沖區:send數據寫到這里

接收緩沖區:recv接收數據

TCP 將應用層的數據看作是無邊界的字節流進行傳輸。發送方可以將多個應用層的消息合并成一個字節流發送,接收方需要自己從字節流中提取出各個消息。例如,應用層發送了兩條消息 “Hello” 和 “World”,TCP 可能會將它們合并成一個字節流 “HelloWorld” 進行發送,接收方需要根據具體的協議來區分這兩條消息。

這張圖展示了 TCP 字節流服務的特性,主要體現以下幾點:

發送端 - **應用層**:應用層通過多次調用 `send()` 函數分別發送 “hello”、“abc”、“test” 這些數據。`send()` 函數用于將應用層數據傳遞給傳輸層。 - **傳輸層**:TCP 協議將這些數據暫存于 TCP 發送緩沖區。TCP 為了提高傳輸效率,會根據自身機制(如窗口大小、擁塞控制等 )對發送緩沖區中的數據進行組合和封裝。如圖中所示,可能會把 “hello” 和 “abc” 組合在一起封裝成一個 TCP 報文段,“test” 單獨封裝成一個 TCP 報文段。這種組合并非嚴格按應用層發送順序和邊界,而是根據 TCP 自身策略。

接收端 - **傳輸層**:接收端的 TCP 協議從網絡中接收 TCP 報文段,先存儲在 TCP 接收緩沖區。 - **應用層**:應用層通過 `recv()` 函數從 TCP 接收緩沖區讀取數據。由于 TCP 發送時可能對數據進行了組合封裝,接收端應用層調用 `recv()` 讀取數據時,不一定能按發送端應用層的原始邊界和順序獲取數據,可能會一次性讀取多個發送端組合封裝的數據,也可能分多次讀取。 總體而言,該圖展示了 TCP 字節流服務中,數據在發送端和接收端的處理過程,突出 TCP 并不保證應用層數據的邊界,而是以字節流形式進行傳輸和處理。 ?

1.3.1 tcp粘包概念

TCP(Transmission Control Protocol,傳輸控制協議)是一種面向連接的、可靠的、基于字節流的傳輸層通信協議。而 TCP 粘包是在使用 TCP 進行數據傳輸時可能遇到的一個常見問題。

TCP 粘包指的是在 TCP 連接中,發送方發送的若干個數據包,到接收方接收時,這些數據包粘連在一起,接收方難以區分哪些字節屬于哪個原始數據包的現象。?

1.3.2?產生 TCP 粘包的原因

發送端原因
  • Nagle 算法:TCP 為了提高傳輸效率,采用了 Nagle 算法。該算法會將小的數據包合并成大的數據包進行發送,以此減少網絡中的數據包數量。例如,當你連續發送多個小數據包時,Nagle 算法可能會將它們合并成一個大的數據包發送,從而造成粘包。
  • TCP 緩沖區:TCP 協議的發送緩沖區用于暫存待發送的數據。如果發送方的數據產生速度大于網絡的發送速度,那么數據就會在緩沖區中累積,當緩沖區滿或者達到一定條件時,就會將緩沖區中的數據一起發送出去,這也可能導致多個數據包粘連在一起。
接收端原因
  • TCP 接收緩沖區:接收端在接收數據時,會將數據先存放在接收緩沖區中。如果接收方沒有及時從緩沖區中讀取數據,后續的數據也會不斷地存入緩沖區,這樣就可能導致多個數據包的數據混合在一起,形成粘包。

1.3.3?解決 TCP 粘包的方法

定長協議

規定每個數據包的長度是固定的。接收方按照固定長度來讀取數據,這樣就可以明確區分每個數據包。

分隔符協議

在每個數據包的末尾添加一個特殊的分隔符,接收方根據分隔符來區分不同的數據包。

消息頭 + 消息體協議

在每個數據包的前面添加一個消息頭,消息頭中包含消息體的長度信息。接收方先讀取消息頭,根據消息頭中的長度信息來讀取相應長度的消息體。

二、服務器接收多個客戶端 用fork做并發

它是一個簡單的TCP服務器程序,它在本地6000端口上監聽連接請求,接受客戶端的連接,并為每個連接創建一個新的進程來處理

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>int main()
{int sockfd = socket(AF_INET,SOCK_STREAM,0);//創建監聽套接字if( -1 == sockfd ){exit(1);}//定義套接字地址結構, ipv4,ipv5,unixstruct sockaddr_in saddr,caddr;memset(&saddr,0,sizeof(saddr));saddr.sin_family = AF_INET;saddr.sin_port = htons(6000);saddr.sin_addr.s_addr = inet_addr("127.0.0.1");//將套接字綁定到指定的IP地址和端口。如果綁定失敗(返回-1),則打印錯誤信息并退出程序。int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));//指定ip portif( -1 == res){printf("bind err\n");exit(1);}//使套接字進入監聽狀態,監聽隊列大小設置為5。如果監聽失敗(返回-1),則退出程序。res = listen(sockfd,5);//設置監聽隊列 大小是5if( -1 == res){exit(1);}//進入一個無限循環,等待客戶端的連接請求。accept函數用于接受連接請求,并將客戶端的地址信息存儲在caddr中。while( 1 ){int len = sizeof(caddr);int c = accept(sockfd,(struct sockaddr*)&caddr,&len);//檢查是否成功接受連接。如果失敗,則繼續下一次循環。if( c < 0 ){continue;}//創建一個新的進程來處理這個連接。如果創建進程失敗,則關閉連接并繼續下一次循環pid_t pid = fork();if( pid == -1 ){close(c);continue;}//在子進程中,進入一個無限循環,接收客戶端發送的數據,并發送"ok"作為響應。如果接收失敗或客戶端關閉連接,則打印信息,關閉連接,并退出子進程。if( pid == 0 ){while( 1 ){char buff[128] = {0};int n = recv(c,buff,127,0);if( n<= 0 ){break;}printf("recv:%s\n",buff);send(c,"ok",2,0);}printf("client close\n");close(c);exit(0);}close(c);}
}

這個程序實現了一個簡單的TCP服務器,它可以在本地6000端口上監聽連接請求,接受客戶端的連接,并為每個連接創建一個新的進程來處理。服務器接收客戶端發送的數據,并發送"ok"作為響應。服務器使用多進程模型來處理多個客戶端的連接。?

TCP客戶端程序cli,它連接到本地服務器(127.0.0.1),發送消息,并接收服務器的響應

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>int main()
{//創建一個TCP套接字。AF_INET 表示使用IPv4地址,SOCK_STREAM 表示使用面向連接的流式套接字。int sockfd = socket(AF_INET,SOCK_STREAM,0);//檢查套接字是否創建成功。如果失敗(返回-1),則退出程序。if( sockfd == -1 ){exit(1);}//定義并初始化服務器的地址結構。memset 用于清零結構體,sin_family 設置為IPv4,sin_port 設置為6000端口(使用htons函數轉換為網絡字節序),sin_addr.s_addr 設置為本地地址127.0.0.1(使用inet_addr函數轉換為網絡字節序)。struct sockaddr_in saddr;memset(&saddr,0,sizeof(saddr));saddr.sin_family = AF_INET;saddr.sin_port = htons(6000);saddr.sin_addr.s_addr = inet_addr("127.0.0.1");//嘗試連接到服務器。如果連接失敗(返回-1),則打印錯誤信息并退出程序。int res = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));if ( res == -1 ){printf("connect err\n");exit(1);}//進入一個無限循環,提示用戶輸入,然后使用fgets函數從標準輸入讀取一行文本(最多127個字符),存儲在緩沖區buff中。while( 1 ){printf("input\n");char buff[128] = {0};fgets(buff,128,stdin);//檢查用戶輸入是否為"end"。如果是,則退出循環。if( strncmp(buff,"end",3) == 0 ){break;}//發送用戶輸入的消息到服務器(不包括換行符),清空緩沖區,接收服務器的響應,并打印出來。send(sockfd,buff,strlen(buff)-1,0);memset(buff,0,128);recv(sockfd,buff,127,0);printf("read:%s\n",buff);}close(sockfd);exit(0);
}

?這個程序實現了一個簡單的TCP客戶端,可以連接到本地服務器,發送消息,并接收服務器的響應。它使用了基本的套接字編程技術,包括創建套接字、連接服務器、發送和接收數據以及關閉套接字。程序通過一個無限循環來持續接收用戶輸入,并在輸入"end"時退出。

?

這兩段代碼分別實現了一個簡單的 TCP 客戶端和一個 TCP 服務器。

?TCP 服務器代碼解釋

這段代碼實現了一個 TCP 服務器,它在本地計算機的 6000 端口上監聽來自客戶端的連接請求。

1. **創建套接字**:
? ?- 使用 `socket` 函數創建一個 TCP 套接字 `sockfd`。

2. **綁定地址**:
? ?- 使用 `bind` 函數將套接字綁定到本地地址 `127.0.0.1` 和端口 `6000` 上。這樣,服務器就準備好在指定的地址和端口上監聽客戶端的連接請求。

3. **監聽連接**:
? ?- 使用 `listen` 函數使套接字進入監聽狀態,等待客戶端的連接請求。監聽隊列的大小設置為 5,這意味著服務器可以同時處理最多 5 個未處理的連接請求。

4. **接受連接**:
? ?- 使用 `accept` 函數接受客戶端的連接請求。每當有新的客戶端連接時,`accept` 函數會返回一個新的套接字 `c`,用于與該客戶端進行通信。

5. **處理客戶端請求**:
? ?- 使用 `fork` 創建一個新的子進程來處理每個客戶端的請求。這樣,服務器可以同時處理多個客戶端的連接。
? ?- 在子進程中,使用 `recv` 函數接收客戶端發送的數據,并使用 `send` 函數發送響應(在這個例子中,響應是字符串 "ok")。
? ?- 當客戶端關閉連接或發生錯誤時,子進程會退出。

6. **關閉連接**:
? ?- 在父進程中,關閉與客戶端的連接套接字 `c`。

?TCP 客戶端代碼解釋

這段代碼實現了一個 TCP 客戶端,它連接到本地服務器(127.0.0.1:6000),發送消息,并接收服務器的響應。

1. **創建套接字**:
? ?- 使用 `socket` 函數創建一個 TCP 套接字 `sockfd`。

2. **連接到服務器**:
? ?- 使用 `connect` 函數連接到服務器的地址 `127.0.0.1` 和端口 `6000` 上。

3. **發送和接收數據**:
? ?- 進入一個無限循環,提示用戶輸入消息。
? ?- 使用 `fgets` 函數從標準輸入讀取用戶輸入的消息。
? ?- 如果用戶輸入 "end",則退出循環,關閉連接并退出程序。
? ?- 使用 `send` 函數將用戶輸入的消息發送到服務器。
? ?- 使用 `recv` 函數接收服務器的響應,并使用 `printf` 函數打印響應。

4. **關閉連接**:
? ?- 在退出循環后,關閉與服務器的連接套接字 `sockfd`。

### 總結

這兩段代碼實現了一個簡單的 TCP 客戶端-服務器通信模型:

- **服務器**:在本地計算機的 6000 端口上監聽客戶端的連接請求,使用多進程模型來處理每個客戶端的請求。服務器接收客戶端發送的數據,并發送 "ok" 作為響應。
- **客戶端**:連接到本地服務器,發送用戶輸入的消息,并接收服務器的響應。

這種模型可以用于實現各種基于 TCP 的網絡應用程序,如聊天程序、文件傳輸等。

會出現僵死進程,所以需要加入信號的使用來解決僵死進程

三、TCP(傳輸控制協議)的狀態轉換圖

展示了TCP連接從建立到關閉的整個過程中可能經歷的各種狀態。

2.1 狀態

1. **CLOSED**:初始狀態,表示連接尚未建立。
2. **LISTEN**:服務器在該狀態監聽來自客戶端的連接請求。
3. **SYN_SENT**:客戶端發送SYN請求連接,等待服務器確認。
4. **SYN_RCVD**:服務器收到SYN請求后,發送SYN+ACK響應,進入此狀態,等待客戶端的確認。
5. **ESTABLISHED**:雙方確認連接后,連接建立,可以開始傳輸數據。
6. **FIN_WAIT_1**:主動關閉連接的一方發送FIN請求,希望關閉連接。
7. **FIN_WAIT_2**:在FIN_WAIT_1狀態下收到對方的ACK后,進入此狀態,等待對方的FIN請求。
8. **CLOSING**:雙方同時發送FIN請求,等待對方的ACK。
9. **TIME_WAIT**:主動關閉連接的一方在發送FIN請求并收到對方的ACK后,進入此狀態,等待一段時間以確保對方收到ACK。
10. **CLOSE_WAIT**:被動關閉連接的一方收到FIN請求后,進入此狀態,等待應用程序關閉連接。
11. **LAST_ACK**:被動關閉連接的一方發送FIN請求后,等待對方的ACK。

2.2 轉換

1. **被動打開**:服務器從CLOSED狀態進入LISTEN狀態,等待客戶端的連接請求。
2. **主動打開**:客戶端從CLOSED狀態發送SYN請求,進入SYN_SENT狀態。
3. **連接建立**:
? ?- 客戶端發送SYN請求,進入SYN_SENT狀態。
? ?- 服務器收到SYN請求,發送SYN+ACK響應,進入SYN_RCVD狀態。
? ?- 客戶端收到SYN+ACK響應,發送ACK確認,進入ESTABLISHED狀態。
? ?- 服務器收到ACK確認,進入ESTABLISHED狀態。
4. **數據傳輸**:在ESTABLISHED狀態下,雙方可以進行數據傳輸。
5. **連接關閉**:
? ?- 主動關閉的一方發送FIN請求,進入FIN_WAIT_1狀態。
? ?- 被動關閉的一方收到FIN請求,發送ACK確認,進入CLOSE_WAIT狀態。
? ?- 被動關閉的一方發送FIN請求,進入LAST_ACK狀態。
? ?- 主動關閉的一方收到FIN請求,發送ACK確認,進入TIME_WAIT狀態。
? ?- TIME_WAIT狀態持續一段時間后,連接關閉,進入CLOSED狀態。?

TCP連接的建立和關閉是一個復雜的過程,涉及到多個狀態和狀態轉換。連接建立需要三次握手(SYN, SYN+ACK, ACK),而連接關閉需要四次揮手(FIN, ACK, FIN, ACK)。這種設計確保了連接的可靠性和數據的完整性。

在Linux系統中使用netstat命令查看網絡連接狀態的輸出結果。netstat是一個常用的網絡工具,用于顯示網絡連接、路由表、接口統計等信息。圖片中的命令netstat -nat用于顯示所有網絡連接和監聽端口,包括TCP和UDP協議,并且不解析服務名稱

  1. 輸出字段

    • Proto:協議類型,如TCP或TCP6。

    • Recv-Q:接收隊列長度。

    • Send-Q:發送隊列長度。

    • Local Address:本地地址和端口。

    • Foreign Address:遠程地址和端口。

    • State:連接狀態,如LISTEN、ESTABLISHED、CLOSE_WAIT等。

    • PID/Program name:進程ID和程序名稱。

  2. 狀態解釋

    • LISTEN:端口正在監聽,等待連接請求。

    • ESTABLISHED:連接已建立,數據可以傳輸。

    • CLOSE_WAIT:被動關閉連接的一方等待關閉連接。

    • FIN_WAIT_1:主動關閉連接的一方等待對方的FIN請求。

    • FIN_WAIT_2:主動關閉連接的一方等待對方的ACK確認。

    • TIME_WAIT:主動關閉連接的一方等待一段時間以確保對方收到ACK。

  • 第一張圖顯示了多個端口處于LISTEN狀態,表示這些端口正在等待連接請求。

  • 第二張圖顯示了一個端口(127.0.0.1:6000)已經完成了三次握手,處于ESTABLISHED狀態,表示連接已經建立。

  • 第三張圖顯示了一個端口(127.0.0.1:6000)處于CLOSE_WAIT狀態,表示被動關閉連接的一方等待關閉連接。

變成time wait端口被占用 狀態服務器不能啟動

為什么需要time wait狀態??

1. 可靠的終止TCP連接

TCP 連接的終止需要通過四次揮手過程來完成。在主動關閉連接的一方發送了 FIN 報文后,它需要等待對方的 ACK 報文。然而,由于網絡延遲或其他原因,這個 ACK 報文可能會丟失或延遲到達。如果主動關閉方在發送 FIN 報文后立即關閉,那么它將無法接收到這個 ACK 報文,從而導致連接沒有被正確關閉。

為了避免這種情況,主動關閉方會進入 TIME_WAIT 狀態,等待一段時間(通常是 2 倍的 MSL,即 Maximum Segment Lifetime,報文段的最大生存時間)。這段時間足夠長,可以確保即使 ACK 報文丟失或延遲,主動關閉方也能夠接收到來自對方的重傳 ACK 報文,從而可靠地終止連接。

2. 保證讓遲來的TCP報文段有足夠的時間被識別并丟棄

TCP 連接的標識是由源 IP 地址、目的 IP 地址、源端口號和目的端口號共同組成的。當一個 TCP 連接被關閉后,這些標識可能會被新的連接所使用。然而,由于網絡延遲或其他原因,舊連接的報文段可能會在連接關閉后仍然存在于網絡中。

如果新的連接使用了相同的標識,那么這些遲來的舊報文段可能會被錯誤地識別為新連接的報文段,從而導致數據混亂。TIME_WAIT 狀態通過等待一段時間,確保所有舊的報文段都已經被丟棄或過期,從而避免這種情況的發生。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/79289.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/79289.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/79289.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

探秘 Ruby 與 JavaScript:動態語言的多面風采

1 語法特性對比&#xff1a;簡潔與靈活 1.1 Ruby 的語法優雅 Ruby 的語法設計旨在讓代碼讀起來像自然語言一樣流暢。它擁有簡潔而富有表現力的語法結構&#xff0c;例如代碼塊、符號等。 以下是一個使用 Ruby 進行數組操作的簡單示例&#xff1a; # 定義一個數組 numbers [1…

點評項目回顧

表結構 基于Session實現登錄流程 發送驗證碼&#xff1a; 用戶在提交手機號后&#xff0c;會校驗手機號是否合法&#xff0c;如果不合法&#xff0c;則要求用戶重新輸入手機號 如果手機號合法&#xff0c;后臺此時生成對應的驗證碼&#xff0c;同時將驗證碼進行保存&#xf…

OpenShift介紹,跟 Kubernetes ,Docker關系

1. OpenShift 簡介 OpenShift是一個開源項目,基于主流的容器技術Docker及容器編排引擎Kubernetes構建。可以基于OpenShift構建屬于自己的容器云平臺。OpenShift的開源社區版本叫OpenShift Origin,現在叫OKD。 OpenShift 項目主頁:https://www.okd.io/。OpenShift GitHub倉庫…

Ubuntu服務器性能調優指南:從基礎工具到系統穩定性提升

一、性能監控工具的三維應用 1.1 監控矩陣構建 通過組合工具搭建立體監控體系&#xff1a; # 實時進程監控 htop --sort-keyPERCENT_CPU# 存儲性能采集 iostat -dx 2# 內存分析組合拳 vmstat -SM 1 | awk NR>2 {print "Active:"$5"MB Swpd:"$3"…

計算機視覺——基于MediaPipe實現人體姿態估計與不良動作檢測

概述 正確的身體姿勢是個人整體健康的關鍵。然而&#xff0c;保持正確的身體姿勢可能會很困難&#xff0c;因為我們常常會忘記。本博客文章將逐步指導您構建一個解決方案。最近&#xff0c;我們使用 MediaPipe POSE 進行身體姿勢檢測&#xff0c;效果非常好&#xff01; 一、…

LSTM結合LightGBM高緯時序預測

1. LSTM 時間序列預測 LSTM 是 RNN&#xff08;Recurrent Neural Network&#xff09;的一種變體&#xff0c;它解決了普通 RNN 訓練時的梯度消失和梯度爆炸問題&#xff0c;適用于長期依賴的時間序列建模。 LSTM 結構 LSTM 由 輸入門&#xff08;Input Gate&#xff09;、遺…

六、adb通過Wifi連接

背景 收集是榮耀X40,數據線原裝全新的&#xff0c;USB連上之后&#xff0c;老是斷&#xff0c;電腦一直叮咚叮咚的響個不停&#xff0c;試試WIFI 連接是否穩定&#xff0c;需要手機和電腦用相同的WIFI. 連接 1.通過 USB 連接手機和電腦(打開USB調試等這些都略過) adb device…

如何理解前端開發中的“換皮“

"換皮"在前端開發中是一個常見的術語&#xff0c;通常指的是在不改變網站或應用核心功能和結構的情況下&#xff0c;只改變其外觀和視覺表現。以下是關于前端"換皮"的詳細理解&#xff1a; 基本概念 定義&#xff1a;換皮(Skinning)是指保持應用程序功能不…

從 Vue 到 React:深入理解 useState 的異步更新

目錄 從 Vue 到 React&#xff1a;深入理解 useState 的異步更新與函數式寫法1. Vue 的響應式回顧&#xff1a;每次賦值立即生效2. React 的狀態更新是異步且批量的原因解析 3. 函數式更新&#xff1a;唯一的正確寫法4. 對比 Vue vs React 狀態更新5. React useState 的核心源碼…

使用Redis實現分布式限流

一、限流場景與算法選擇 1.1 為什么需要分布式限流 在高并發系統中&#xff0c;API接口的突發流量可能導致服務雪崩。傳統的單機限流方案在分布式環境下存在局限&#xff0c;需要借助Redis等中間件實現集群級流量控制。 1.2 令牌桶算法優勢 允許突發流量&#xff1a;穩定速…

快速搭建WordPress網站的主題

WP快主題(wpkuai.com )是一款由知名WordPress專業團隊打造的專業化WordPress主題&#xff0c;旨在讓用戶使用該wordpress主題快速搭建網站。 WP快主題專注于快速搭建WordPress網站的主題解決方案。其主題設計注重簡潔性與高效性&#xff0c;旨在幫助用戶快速完成網站的搭建和部…

STM32江科大----------PID算法

聲明&#xff1a;本人跟隨b站江科大學習&#xff0c;本文章是觀看完視頻后的一些個人總結和經驗分享&#xff0c;也同時為了方便日后的復習&#xff0c;如果有錯誤請各位大佬指出&#xff0c;如果對你有幫助可以點個贊小小鼓勵一下&#xff0c;本文章建議配合原視頻使用?? 如…

將JSON格式的SQL查詢轉換為完整SQL語句的實戰解析

一、背景與需求 在現代數據處理中,JSON格式因其靈活性和可讀性,常被用于定義SQL查詢的結構。然而,直接編寫JSON格式的SQL指令后,如何將其轉換為可執行的SQL語句是開發者常遇到的挑戰。本文將通過一個Python函數和多個實際案例,解析如何將JSON結構轉換為完整的SQL語句,并…

java CountDownLatch用法簡介

CountDownLatch倒計數鎖存器 CountDownLatch&#xff1a;用于協同控制一個或多個線程等待在其他線程中執行的一組操作完成&#xff0c;然后再繼續執行 CountDownLatch用法 構造方法&#xff1a;CountDownLatch(int count)&#xff0c;count指定等待的條件數&#xff08;任務…

Leetcode - 雙周賽135

目錄 一、3512. 使數組和能被 K 整除的最少操作次數二、3513. 不同 XOR 三元組的數目 I三、3514. 不同 XOR 三元組的數目 II四、3515. 帶權樹中的最短路徑 一、3512. 使數組和能被 K 整除的最少操作次數 題目鏈接 本題實際上求的就是數組 nums 和的余數&#xff0c;代碼如下&…

【后端】【python】利用反射器----動態設置裝飾器

&#x1f4d8; Python 裝飾器進階指南 一、裝飾器本質 ? 本質概念 Python 裝飾器的本質是 函數嵌套 返回函數&#xff0c;它是對已有函數的增強&#xff0c;不修改原函數代碼&#xff0c;使用語法糖 decorator 實現包裹效果。 def my_decorator(func):def wrapper(*args, …

Nodejs Express框架

參考&#xff1a;Node.js Express 框架 | 菜鳥教程 第一個 Express 框架實例 接下來我們使用 Express 框架來輸出 "Hello World"。 以下實例中我們引入了 express 模塊&#xff0c;并在客戶端發起請求后&#xff0c;響應 "Hello World" 字符串。 創建 e…

Docker Swarm 集群

Docker Swarm 集群 本文檔介紹了 Docker Swarm 集群的基本概念、工作原理以及相關命令使用示例&#xff0c;包括如何在服務調度中使用自定義標簽。本文檔適用于需要管理和擴展 Docker 容器化應用程序的生產環境場景。 1. 什么是 Docker Swarm Docker Swarm 是用于管理 Docker…

充電寶項目中的MQTT(輕量高效的物聯網通信協議)

文章目錄 補充&#xff1a;HTTP協議MQTT協議MQTT的核心特性MQTT vs HTTP&#xff1a;關鍵對比 EMQX項目集成EMQX集成配置客戶端和回調方法具體接口和方法處理處理類 補充&#xff1a;HTTP協議 HTTP是一種應用層協議&#xff0c;使用TCP作為傳輸層協議&#xff0c;默認端口是80…

【iOS】UIPageViewController學習

UIPageViewController學習 前言創建一個UIPageViewController最簡單的使用 UIPageViewController的方法說明&#xff1a;效果展示 UIPageViewController的協議方法 前言 筆者最近在寫項目時想實現一個翻書效果&#xff0c;上網學習到了UIPageViewController今天寫本篇博客總結…