TCP如何保證可靠傳輸

一、連接建立

當兩台計算機建立TCP連接時,需要進行三次握手。首先客戶端向服務端發送連接請求報文,如果服務端收到了請求報文,會向客戶端發送一個確認報文,表示可以建立連接。客戶端收到確認之後還會向服務器發送一個確認報文,表示連接已經建立。

// TCP連接建立的示例代碼

// 客戶端發送連接請求報文
struct tcp_header request;
request.destination_port = SERVER_PORT;
request.source_port = CLIENT_PORT;
request.sync = 1; // 同步位設置為1

send_tcp_packet(request);

// 服務端發送確認報文
struct tcp_header response;
response.source_port = SERVER_PORT;
response.destination_port = CLIENT_PORT;
response.ack = 1; // 確認位設置為1
response.acknowledgment_number = request.sequence_number + 1;

send_tcp_packet(response);

// 客戶端發送確認報文
struct tcp_header confirm;
confirm.source_port = CLIENT_PORT;
confirm.destination_port = SERVER_PORT;
confirm.ack = 1; // 確認位設置為1
confirm.acknowledgment_number = response.sequence_number + 1;

send_tcp_packet(confirm);

二、數據傳輸

在TCP連接建立之後,數據傳輸分為兩個部分:發送方將數據拆分成多個報文段(segment),每個報文段都有一個序號和確認號,表示該報文段所包含的數據在整個數據流中的位置,接收方接收到報文段後需要按序號重新組裝成完整的數據。

當發送方發送了一個報文段之後,會等待接收方發送確認消息,表示已經成功接收到數據。如果沒有收到確認消息,說明數據包丟失,發送方會重新發送該數據包,接收方收到重發的數據包後會判斷該數據包是否已經收到過,如果收到過就可以丟棄,否則就可以重新組裝成完整的數據。

// TCP數據傳輸的示例代碼

// 發送方代碼
struct tcp_header segment;
segment.source_port = CLIENT_PORT;
segment.destination_port = SERVER_PORT;
segment.sequence_number = send_base; // 發送基準序號
segment.acknowledgment_number = receive_base; // 確認基準序號

while (not_all_sent) { // 發送所有數據
    if (next_byte_to_send  receive_base) { // 接收到了缺失的數據
    send_ack(receive_base); // 發送確認消息
} else { // 接收到了已經接收過的數據
    send_ack(receive_base); // 發送確認消息
}

三、流量控制

TCP連接中的每一方都有一個緩存區,可以存儲已經接收到的數據或者等待發送的數據。為了防止發送方發送過多數據導致接收方無法及時處理,TCP使用了滑動窗口的技術進行流量控制。發送方不可以發送超出窗口大小的數據,接收方需要在處理完窗口內的數據之後向發送方發送確認消息,告知發送方可以發送更多的數據。

// TCP流量控制的示例代碼

// 發送方代碼
struct tcp_header segment;
segment.source_port = CLIENT_PORT;
segment.destination_port = SERVER_PORT;
segment.sequence_number = send_base; // 發送基準序號
segment.acknowledgment_number = receive_base; // 確認基準序號

while (not_all_sent) {
    if (next_byte_to_send = receive_base && received_segment.sequence_number < receive_base + receive_window) { // 接收窗口內的數據
    append_data(received_segment.payload);
    receive_base = received_segment.sequence_number + received_segment.payload.length();
    receive_window = get_receive_window_size();
    send_ack(receive_base); // 發送確認消息
} else { // 接收窗口外的數據
    send_ack(receive_base); // 發送確認消息
}

四、擁塞控制

TCP使用了四種擁塞控制算法,分別是慢開始(slow start)、擁塞避免(congestion avoidance)、快速重傳(fast retransmit)、快速恢復(fast recovery)。

慢開始是指在連接建立時,發送方先以指數級別增加發送窗口的大小,直到達到某個閾值,然後再以線性級別增長發送窗口。如果在發送數據的過程中出現了亂序或者丟失的數據包,就需要採用快速重傳和快速恢復的技術,快速重傳就是在連續收到三個重複的確認消息之後立即重傳數據包,快速恢復是在重傳數據包之後將發送窗口減半然後進行擁塞避免。

// TCP擁塞控制的示例代碼

// 發送方代碼
struct tcp_header segment;
segment.source_port = CLIENT_PORT;
segment.destination_port = SERVER_PORT;
segment.sequence_number = send_base; // 發送基準序號
segment.acknowledgment_number = receive_base; // 確認基準序號
int cwnd = 1; // 初始發送窗口大小為1

while (not_all_sent) {
    if (next_byte_to_send = 3) { // 收到三個重複確認消息,觸發快速重傳和快速恢復
        resend_segment();
        cwnd /= 2;
        receive_window = get_receive_window_size();
        cwnd = cwnd + 1;
    } else if (next_byte_to_send - send_base == cwnd) { // 發送窗口滿了,進入擁塞避免狀態
        cwnd ++;
    }
}

// 接收方代碼
struct tcp_header received_segment;
received_segment = wait_for_segment();

if (received_segment.sequence_number >= receive_base && received_segment.sequence_number  send_base) { // 收到新的確認消息,更新發送窗口大小
    cwnd = min(received_segment.acknowledgment_number - send_base, cwnd * 2);
    send_base = received_segment.acknowledgment_number;
}

原創文章,作者:RXQNS,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/372088.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
RXQNS的頭像RXQNS
上一篇 2025-04-24 06:40
下一篇 2025-04-24 06:40

相關推薦

發表回復

登錄後才能評論