Wireshark抓包:理解TCP三次握手和四次挥手过程

TCP是一种面向连接、端到端可靠的协议,它被设计用于在互联网上传输数据和确保成功传递数据和消息。本节来介绍一下TCP中的三次握手和四次挥手。

1 TCP头部格式

TCP头部占据TCP段的前20个字节,其中包含端到端TCP套接字的参数和状态。如下图所示:

在这里插入图片描述

下面来逐个解释一下这些字段:

  • 源端口(Source port):16位,用于标识源端口号(发送方的TCP端口)
  • 目标端口(Destination port):16位,用于标识目标端口号(接收方的TCP端口)
  • 序列号(Sequence number):32位,指示在TCP会话期间发送了多少数据。当建立新的TCP连接时,初始序列号是一个随机值。
  • 确认号(``Acknowledgment Number`):32位,由接收方用于请求下一个TCP段。如果设置了ACK控制位,该字段包含段发送方期望接收的下一个序列号的值。一旦建立了连接,这个字段总是被发送。
  • 数据偏移(Data offset):4位,显示头部中32位字的数量,也称为头部长度
  • 保留数据(Reserved data):6位,保留字段,始终设置为零
  • 控制位标志(Control bit Flags):TCP使用9位控制标志来管理特定情况下的数据流,例如建立连接、发送数据和终止连接
    • URG: 与后面的紧急指针字段相关,当设置了此位时,数据应被视为优先于其他数据。
    • ACK: 与ACK相关,确认字段用于指示已成功接收到的数据量,如果设置了此字段,说明发送方期望接收方继续发送下一个TCP段
    • PSH: 推送功能,表示发送方希望接收方立即传输数据,而不必等到整个TCP段的数据都准备好再传输
    • RST: 重置连接,仅在存在无法恢复的错误时使用
    • SYN: 同步序列号,此标志用于设置初始序列号
    • FIN: 完成位用于结束TCP连接,因为TCP是全双工连接,所以双方都必须使用FIN位来结束连接
  • 窗口(Window):16位,指定接收方愿意接收多少字节
  • 校验和(Checksum):16位,用于对头部和数据进行错误检查
  • 紧急指针(Urgent Pointer):如果设置了URG控制标志,该值表示与序列号的偏移,指示最后一个紧急数据字节
  • 选项(Options):可选,长度可为0~320位之间的任意大小

2 wireshark抓包分析

程序流程:服务端监听本地环回地址127.0.0.1的12345端口,客户端则连接这个端口,连接上后服务端发送一个Hello, World!给客户端。

先来了解一下SEQACK的概念:

2.1 SEQ和ACK

客户端和服务器之间建立TCP连接时会进行三次握手。先来理解一下SEQACK的概念:

  1. 序列号(SEQ): 表示发送方发送的数据的起始位置。每发送一个新的数据段,序列号就会递增。
  2. 确认号(ACK): 表示接收方期望下次收到的数据的序列号。当接收方收到数据后,它会发送一个带有确认号的ACK,告诉发送方它已成功接收到了特定序列号之前的所有数据。
  3. 下一个期望的ACK: 当接收方收到一段数据时,ACK表示已成功接收的数据的下一个期望的序列号。因此,下一个期望的ACK号通常是上一个ACK号加上接收到的数据的长度。

2.2 三次握手

1、客户端发送SYN给服务端

在这里插入图片描述

  • 在wireshark中SEQ使用相对0的值,为的是方便分析,所以这里是0

从上图中可以看到SYN标识被设置:

在这里插入图片描述

2.服务端回复带有SEQACKSYN-ACK数据包

在这里插入图片描述

如下图所示:

在这里插入图片描述

3.客户端向服务器发送一个带有ACK号的数据包,确认服务器的序列号

在这里插入图片描述

如下图所示:

在这里插入图片描述

此时双方的SEQ已同步,以上就是三次握手的内容。下面客户端和服务器可以独立地发送和接收数据。

4.服务器向客户端发送“Hello, World!”

在这里插入图片描述

5.客户端向服务器发送一个ACK号,确认服务器的消息

上一个ACK号为1,长度为13,因此ACK号将为13+1=14。

在这里插入图片描述

2.3 四次挥手

接着上面的抓包来看,在程序中,服务端发送完“Hello, World!”后就关闭了客户端的socket。

1.服务端发送FIN给客户端

在这里插入图片描述

如下图所示:

在这里插入图片描述

2.客户端向服务器发送一个ACK号,确认服务器的FIN请求

在这里插入图片描述

如下图所示:

在这里插入图片描述

3.TCP是一种全双工连接,因此,客户端也向服务器发送一条消息以关闭连接

  • 前面的图中最后一行是红色的RST是我不小心直接关闭了程序,下面的图为重新抓的包,注意看最后两条即可

在这里插入图片描述

如下图所示:

在这里插入图片描述

4.服务器向客户端发送一个ACK号,确认客户端的FIN请求

在这里插入图片描述

如下图所示:

在这里插入图片描述

3 程序

本文的代码使用Windows环境下的网络编程库,所以需要在链接库中增加ws2_32

服务端

// Server.c

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>

int main() {
    WSADATA wsaData;
    SOCKET listenSocket, clientSocket;
    struct sockaddr_in serverAddr, clientAddr;
    int addrLen = sizeof(clientAddr);
    char buffer[1024] = "Hello, World!";

    // Initialize Winsock
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        fprintf(stderr, "WSAStartup failed\n");
        return 1;
    }

    // Create a socket
    if ((listenSocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
        fprintf(stderr, "Socket creation failed\n");
        WSACleanup();
        return 1;
    }

    // Set up server address information
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    serverAddr.sin_port = htons(12345);

    // Bind the socket
    if (bind(listenSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
        fprintf(stderr, "Bind failed\n");
        closesocket(listenSocket);
        WSACleanup();
        return 1;
    }

    // Listen for incoming connections
    if (listen(listenSocket, SOMAXCONN) == SOCKET_ERROR) {
        fprintf(stderr, "Listen failed\n");
        closesocket(listenSocket);
        WSACleanup();
        return 1;
    }

    printf("Server listening on 127.0.0.1:12345\n");

    // Accept a connection from a client
    if ((clientSocket = accept(listenSocket, (struct sockaddr*)&clientAddr, &addrLen)) == INVALID_SOCKET) {
        fprintf(stderr, "Accept failed\n");
        closesocket(listenSocket);
        WSACleanup();
        return 1;
    }

    // Send data to the client
    send(clientSocket, buffer, strlen(buffer), 0);

    printf("Data sent to the client\n");

    // Clean up
    closesocket(clientSocket);
    closesocket(listenSocket);
    WSACleanup();

    return 0;
}

客户端

// Client.c

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>

int main() {
    WSADATA wsaData;
    SOCKET clientSocket;
    struct sockaddr_in serverAddr;
    char buffer[1024];

    // Initialize Winsock
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        fprintf(stderr, "WSAStartup failed\n");
        return 1;
    }

    // Create a socket
    if ((clientSocket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
        fprintf(stderr, "Socket creation failed\n");
        WSACleanup();
        return 1;
    }

    // Set up server address information
    memset(&serverAddr, 0, sizeof(serverAddr));
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    serverAddr.sin_port = htons(12345);

    // Connect to the server
    if (connect(clientSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
        fprintf(stderr, "Connection failed\n");
        closesocket(clientSocket);
        WSACleanup();
        return 1;
    }

    // Receive data from the server
    int bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0);
    if (bytesRead > 0) {
        buffer[bytesRead] = '\0'; // Null-terminate the received data
        printf("Received data from server: %s\n", buffer);
    } else {
        fprintf(stderr, "Error receiving data\n");
    }
    while(1)
    {
        if(recv(clientSocket, buffer, sizeof(buffer), 0) == 0)
        {
            break;
        }
    }
    // Clean up
    closesocket(clientSocket);
    WSACleanup();

    return 0;
}
  • 5
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: TCP三次握手和四次挥手TCP协议建立和关闭连接时所采用的步骤。 三次握手是在客户端和服务器之间建立TCP连接时的过程。首先,客户端向服务器发送一个请求连接的数据包,该数据包包含一个随机生成的序列号(SYN),表示客户端希望建立连接。服务器接收到该请求后,向客户端回复一个确认连接的数据包,该数据包包含其自己生成的一个随机序列号(SYN-ACK),表示服务器同意建立连接。最后,客户端再次向服务器发送一个确认连接的数据包,该数据包中包含服务器的序列号加一(ACK),表示客户端接受服务器的连接请求。这样,TCP连接就建立起来了。 四次挥手是在客户端和服务器关闭TCP连接时的过程。首先,客户端发送一个关闭连接的请求数据包(FIN),表示客户端想要关闭连接。服务器收到该请求后,向客户端回复一个确认关闭连接的数据包(ACK),但自己的数据可能没有发送完毕。服务器等到自己的数据发送完毕后,发送一个自己的关闭连接请求数据包(FIN),表示服务器也希望关闭连接。客户端收到服务器的请求后,回复一个确认关闭连接的数据包(ACK),然后等待一段时间,确保服务器收到了该数据包。最后,客户端和服务器都关闭连接,四次挥手过程完成。 通过Wireshark抓包分析TCP三次握手和四次挥手可以观察到每个数据包的源地址、目标地址、序列号、确认号等信息。可以通过Wireshark的过滤功能筛选出TCP协议相关的数据包进行分析。通过分析数据包的交互过程,可以确认连接建立和关闭的状态是否符合预期,并可以进一步分析网络延迟、丢包等问题。 综上所述,Wireshark抓包分析TCP三次握手和四次挥手可以帮助我们深入理解TCP连接的建立和关闭过程,以及发现网络故障的根源。 ### 回答2: TCP是一种常用的传输层协议,它通过进行三次握手来建立连接,并进行四次挥手来终止连接。 三次握手过程如下: 1. 客户端发送一个SYN标志位的TCP报文段给服务器,表示请求建立连接; 2. 服务器收到请求后,回复一个带有SYN和ACK标志位的TCP报文段给客户端,表示同意建立连接; 3. 客户端收到服务器的回复后,再次发送一个带有ACK标志位的TCP报文段给服务器,表示连接建立成功。 四次挥手的过程如下: 1. 客户端发送一个FIN标志位的TCP报文段给服务器,表示希望断开连接; 2. 服务器收到请求后,回复一个带有ACK标志位的TCP报文段给客户端,表示确认收到断开请求; 3. 服务器完成数据的发送后,发送一个带有FIN标志位的TCP报文段给客户端,表示自己也要断开连接; 4. 客户端收到服务器的断开请求后,发送一个带有ACK标志位的TCP报文段给服务器,表示确认断开,并进入TIME_WAIT状态。 在三次握手过程中,第一次握手是客户端发起的,第二次握手是服务器回复同意建立连接,第三次握手是客户端回复确认连接。这个过程是为了确保双方都同意建立连接,以保证数据传输的可靠性。 在四次挥手的过程中,首先客户端发送断开请求,服务器回复确认,然后服务器发送断开请求,客户端回复确认。这个过程是为了保证双方都断开连接,并确保数据完整性。 Wireshark是一款网络抓包分析工具。使用Wireshark可以捕获网络数据包,并对数据包进行解析和分析。通过Wireshark,我们可以看到每个TCP报文段的具体内容,并对三次握手和四次挥手过程进行详细分析。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tilblackout

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值