TCP高频知识点

简介: TCP高频知识点

本篇文章主要讲述一下在面试过程中TCP的高频知识点

1.TCP三次握手流程图:

  1. 客户端发送一个SYN(同步)报文段给服务器,选择一个初始序列号,并设置SYN标志位为1。
  2. 服务器接收到客户端的SYN报文段后,回复一个ACK(确认)报文段,其中确认号设置为客户端发送的序列号加1,同时也选择一个初始序列号,并设置SYN和ACK标志位为1。
  3. 客户端接收到服务器的ACK报文段后,回复一个ACK报文段作为确认应答。其中确认号设置为服务器发送的序列号加1。

2.TCP的基本性质

1.TCP是全双工的 可靠的 基于字节流的传输协议

2.同一个五元组只允许建立一条连接

3.通过序列号可以实现数据包按序收发 丢失重传

3.TCP三次握手的作用

  1. 确认双方的通信能力:通过三次握手,可以确保客户端和服务器都正常工作并且能够互相通信。
  2. 同步双方的初始序列号:TCP连接需要使用序列号来分割数据流,并提供可靠性保证。通过握手过程中的交换序列号,双方可以确定初始的序列号值。
  3. 防止旧连接影响新连接:在网络中可能存在延迟、重复或失序等问题,通过三次握手可以避免由于旧连接还未完全关闭而导致新连接产生混淆

TCP为什么不能进行两次挥手

1.无法避免旧的重复的初始化  从而造成资源的浪费

2.无法同步双端其实序列号 从而无法保证可靠传输

TCP四次挥手:

  1. 客户端发送一个终止连接请求给服务器,即发送一个FIN(Finish)报文段。
  2. 服务器接收到FIN报文段后,回复一个确认应答ACK报文段,表示已经接收到关闭请求。
  3. 服务器通知上层应用程序关闭连接,并发送一个FIN报文段给客户端。
  4. 客户端接收到服务器的FIN报文段后,回复一个确认应答ACK报文段,表示已经接收到服务器的关闭请求。
  5. 等待一段时间,确保双方都收到了对方的确认应答ACK报文段,然后彻底关闭连接。

TCP四次挥手的意义:

首先,TCP是一个全双工的协议,意味着客户端和服务器可以同时发送和接收数据。因此,在关闭连接时需要进行一系列步骤来确保双方都能够知道对方的关闭意图,并处理未及时接收的数据。

其次,四次挥手中包含两个方向上各两个报文段(FIN和ACK),用于通知对方自己准备关闭连接。这样可以保证每一方都有机会发出确认,避免一方过早地关闭连接导致数据丢失或重传。

还有一个重要的原因是,客户端在发送最后一个ACK报文段之后进入了"时间等待"状态。这是为了等待一定时间,以确保网络中所有延迟传输的数据都被接收完毕。如果立即关闭连接而不等待,可能会导致服务端发送的最后一部分数据无法被客户端正常接收。

TCP三次握手代码实例:

#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
int main() {
    // 创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
    // 服务器地址和端口
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8888);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    // 发起连接请求
    connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
    char buffer[1024];
    
    // 发送SYN报文段(第一次握手)
    send(sockfd, "SYN", strlen("SYN"), 0);
    // 接收服务端返回的SYN+ACK报文段(第二次握手)
    memset(buffer, 0, sizeof(buffer));
    recv(sockfd, buffer, sizeof(buffer)-1, 0);
    std::cout << "Received: " << buffer << std::endl;
    if (strcmp(buffer, "SYN+ACK") == 0) {
        // 发送ACK报文段(第三次握手)
        send(sockfd, "ACK", strlen("ACK"), 0);
        std::cout << "Handshake completed." << std::endl;
    } else {
        std::cout << "Handshake failed." << std::endl;
        close(sockfd);
        return -1;
    }
     // 关闭连接
     close(sockfd);
     return 0;
}

在这个示例代码中,首先创建一个套接字(socket)(注意socket使用),然后设置服务器地址和端口。使用connect函数发起连接请求。接下来,发送SYN报文段表示客户端希望建立连接。通过recv函数接收服务端返回的SYN+ACK报文段,并进行判断。如果接收到正确的报文段,则向服务端发送ACK报文段确认连接建立成功。最后,关闭连接。

TCP四次挥手代码实例:

#include <iostream>
#include <cstring>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
int main() {
    // 创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
    // 服务器地址和端口
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(8888);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    // 发起连接请求
    connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
    char buffer[1024];
    
    // 发送FIN报文段(第一次挥手)
    send(sockfd, "FIN", strlen("FIN"), 0);
    // 接收服务端返回的ACK报文段(第二次挥手)
    memset(buffer, 0, sizeof(buffer));
    recv(sockfd, buffer, sizeof(buffer)-1, 0);
    
     std::cout << "Received: " << buffer << std::endl;
     if (strcmp(buffer, "ACK") == 0) {
         // 接收服务端发送的FIN报文段(第三次挥手)
         memset(buffer, 0, sizeof(buffer));
         recv(sockfd, buffer, sizeof(buffer)-1, 0);
         
         std::cout << "Received: " << buffer << std::endl;
         if (strcmp(buffer,"FIN") == 0) {
             // 发送ACK报文段(第四次挥手)
             send(sockfd,"ACK",strlen("ACK"), 0);
             std::cout << "Connection closed." << std::endl;
         }
     } else {
         std::cout << "Handshake failed." << std::endl;
         close(sockfd);
         return -1;
     }
    // 关闭连接
    close(sockfd);
    return 0;
}

在这个示例代码中,首先创建一个套接字(socket),然后设置服务器地址和端口。使用connect函数发起连接请求。接下来,发送FIN报文段表示客户端希望关闭连接。通过recv函数接收服务端返回的ACK报文段,并进行判断。如果接收到正确的ACK报文段,则继续接收服务端发送的FIN报文段。最后,向服务端发送ACK报文段确认关闭连接

好了 本篇文章就到这里结束了 在这里 小编给大家推荐一个课程:

https://xxetb.xetslk.com/s/2PjJ3T

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
域名解析 Kubernetes 网络协议
k8s教程(service篇)-pod的dns域名
k8s教程(service篇)-pod的dns域名
2961 0
|
SQL 算法
【hacker的错误集】html5lib使用报错Couldn‘t find a tree builder with the features you requested: html5lib
分析得出:bs4的特征没有找到:找不到具有您请求功能的树生成器:html5lib。您需要安装解析器库吗?
497 0
【hacker的错误集】html5lib使用报错Couldn‘t find a tree builder with the features you requested: html5lib
|
10月前
|
Rust IDE Java
一些常见的IDE和工具链的配置指南
一些常见的IDE和工具链的配置指南
235 10
|
存储 索引 Python
生信教程:使用全基因组SNP数据进行ABBA-BABA分析
生信教程:使用全基因组SNP数据进行ABBA-BABA分析
|
缓存 网络协议 算法
c++理论篇(一) ——浅谈tcp缓存与tcp的分包与粘包
c++理论篇(一) ——浅谈tcp缓存与tcp的分包与粘包
420 0
c++理论篇(一) ——浅谈tcp缓存与tcp的分包与粘包
|
SQL Oracle 关系型数据库
SQL查询结果导出方法详析及实践指南
导出SQL查询结果是数据库管理中的一个重要环节。不同的数据库系统提供了各自的工具和方法来完成这项任务。选择合适的方法取决于具体的应用场景、数据规模和个人偏好。无论是在命令行中使用简单的SQL语句,还是通过GUI工具或编程语言实现自动化脚本,都有助于提高工作效率,简化数据管理流程。
|
Shell PHP 数据安全/隐私保护
CTFShow-WEB入门篇命令执行详细Wp(29-40)
CTFShow-WEB入门篇命令执行详细Wp(29-40)
574 0
|
NoSQL Java API
SpringBoot项目中防止表单重复提交的两种方法(自定义注解解决API接口幂等设计和重定向)
SpringBoot项目中防止表单重复提交的两种方法(自定义注解解决API接口幂等设计和重定向)
1366 0
|
SQL Java 程序员
聊聊lambda
聊聊lambda
81 1
|
存储 算法 搜索推荐
请解释一下图形存储数据库的工作原理,并提供一个使用图形存储数据库的实际应用场景。
请解释一下图形存储数据库的工作原理,并提供一个使用图形存储数据库的实际应用场景。
209 0