เหตุใดบิต ACK จึงถูกตั้งค่าเสมอในแพ็กเก็ต TCP เกือบทั้งหมดที่คาดว่าจะมี SYN แรก [ทำซ้ำ]

ฉันได้เรียนรู้ว่าบิต ACK ในแพ็กเก็ต TCP ถูกตั้งค่าเมื่อตอบกลับข้อความที่เพียร์ส่ง ซึ่งหมายความว่า "ตกลง ฉันได้รับแพ็กเก็ตทั้งหมดที่มีหมายเลขลำดับน้อยกว่า แล้ว ตอนนี้ฉันคาดว่าจะได้รับแพ็กเก็ตแล้ว โดยมีหมายเลขลำดับเท่ากับ " แต่จากประสบการณ์ของฉัน ดูเหมือนว่าบิต ACK จะถูกตั้งค่าไว้ในแพ็กเก็ต TCP เกือบทั้งหมดเสมอ คาดว่าจะเป็นแพ็กเก็ต SYN แรก

ประสบการณ์ของฉันเป็นดังนี้:

  1. เซิร์ฟเวอร์จะฟังพอร์ต SERVER_SOCK (ซึ่งก็คือ 32413)
  2. ลูกค้าจะเชื่อมต่อกับเซิร์ฟเวอร์
  3. เซิร์ฟเวอร์จะส่งข้อความ ("สวัสดี") ไปยังลูกค้า
  4. ลูกค้าอ่านข้อความแล้วฉันกด Enter เพื่อปิดไคลเอนต์
  5. ฉันกด Enter เพื่อปิดเซิร์ฟเวอร์

รหัส C สำหรับประสบการณ์ของฉันมีดังต่อไปนี้:

ลูกค้า

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define SERVER_SOCK 32413

int main() {
    // Create socket
    int sock = socket(AF_INET, SOCK_STREAM, 0);

    // Connect to server
    struct sockaddr_in server_addr;
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    server_addr.sin_port = htons(SERVER_SOCK);
    connect(sock, (struct sockaddr*) &server_addr, sizeof(server_addr));
    printf("Connected\n");

    // Read message from server
    char msg[32] = {0};
    read(sock, msg, 32);
    printf("%s\n", msg);

    printf("Press ENTER to call close()");
    getchar();
    close(sock);
    return 0;
}

เซิร์ฟเวอร์

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define SERVER_SOCK 32413
#define LISTEN_BACKLOG 3

int main() {
    int server_sock, client_sock;
    struct sockaddr_in server_addr, client_addr;
    socklen_t client_len = sizeof(client_addr);

    // Create socket
    server_sock = socket(AF_INET, SOCK_STREAM, 0);

    // Set address and port
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(SERVER_SOCK);

    // Bind to port and begin listening
    bind(server_sock, (struct sockaddr*) &server_addr, sizeof(server_addr));
    listen(server_sock, LISTEN_BACKLOG);
    printf("Server is listening\n");

    // Accept client socket
    client_sock = accept(server_sock, (struct sockaddr*) &client_addr, &client_len);
    printf("Connection accepted\n");

    // Send message to client
    send(client_sock, "hello", 5, 0);

    printf("Press enter to call close()");
    getchar();
    close(client_sock);
    close(server_sock);

    return 0;
}

ฉันใช้ wireshark เพื่อจับแพ็กเก็ต และผลลัพธ์จะแสดงดังนี้:

ผลลัพธ์ wireshark

อย่างที่คุณเห็น ทุกแพ็กเก็ตยกเว้นแพ็กเก็ตแรกจะมีการตั้งค่าบิต ACK ไว้ แล้วทำไมล่ะ? แพ็กเก็ต #4, #6 และ #8 รับทราบอะไรบ้าง


tcp
person TsReaper    schedule 12.04.2018    source แหล่งที่มา
comment
มันไม่ใช่คำถามเดียวกัน สิ่งที่ฉันถามคือเหตุใดบิต ACK ของเกือบทุกแพ็กเก็ตจึงถูกตั้งค่า รวมถึงแพ็กเก็ตที่ส่งข้อมูลไปยังผู้อื่นด้วย คำถามซ้ำที่เป็นไปได้คือหากจำเป็นต้องใช้ SYN ในแต่ละครั้งที่เราพยายามส่งข้อมูลไปยังเพียร์ คำตอบสำหรับคำถามซ้ำซ้อนที่เป็นไปได้ไม่สามารถอธิบายปรากฏการณ์ที่ฉันกำลังเผชิญอยู่ได้   -  person TsReaper    schedule 12.04.2018
comment
นั่นเป็นเรื่องจริง แต่ฉันคิดว่าคำตอบสำหรับคำถามนั้นยังตอบคำถามของคุณด้วย โดยเฉพาะบิตนี้: ACK เป็นเพียงแฟล็กและฟิลด์ในส่วนหัว TCP การส่งหนึ่งรายการต้องใช้แบนด์วิดท์อย่างน้อยก็ที่ส่วนหัว รวมถึงสิ่งใดก็ตามที่เลเยอร์ด้านล่างจะยึดติด แต่เซ็กเมนต์ข้อมูลรวมทุกอย่างไว้แล้ว...ดังนั้นหากคุณส่งข้อมูล คุณสามารถส่ง ACK พร้อมกันได้ฟรี และย่อหน้าและแผนภาพด้านล่างนั้น   -  person TypeIA    schedule 12.04.2018
comment
ack ถ่ายทอดข้อมูลไปยังผู้ส่งเกี่ยวกับข้อมูลที่ถูกส่งสำเร็จ ack ที่ซ้ำกันใช้สำหรับการส่งซ้ำ/การกู้คืนอย่างรวดเร็ว ดังนั้นการตั้งค่าสถานะ ack เฉพาะเมื่อได้รับข้อมูลใหม่จะทำให้ประสิทธิภาพการทำงานไม่ดี นอกจากนี้ยังไม่มีค่าใช้จ่ายในการตั้งค่า ack bit   -  person FormerNcp    schedule 14.04.2018