TCP常见问题详解

简介: TCP常见问题详解

本篇文章我们介绍一下 在我们的面试中和实际开发中使用TCP遇到的问题

1.TCP在什么情况下出现大量的time_event

什么是time_event?

我们首先要弄清楚TIME_WAIT状态是什么?TIME_WAIT状态是主动关闭TCP连接的一方(即先发起FIN包的一方),在发送完最后一个ACK包后进入的状态。系统需要在TIME_WAIT状态下等待2MSL(maximum segment lifetime )后才能释放连接(端口)。根据RFC 793 MSL是2分钟,一般的TCP实现有30秒、1分钟和2分钟不等。进入TIME_WAIT状态等待2MSL主要有两个目的:一方面是主动关闭连接的一方在对方没有收到最后一个ACK包时(这时对方还会重发FIN,收到两个FIN的时间间隔一定小于2MSL)有时间可以重发ACK包,另一方面处于TIME_WAIT的连接(IP和端口组合)不能重用,这样可以保证被重新分配的socket不会受到之前残留的延迟重发报文影响。

由于主动关闭TCP连接的一方才会进入TIME_WAIT状态,一般情况服务器端不会出现TIME_WAIT状态,因为大多数情况都是客户端主动发起连接并主动关闭连接。但是某些服务如pop/smtp、ftp却是服务端收到客户端的QUIT命令后主动关闭连接,这就造成这类服务器上容易出现大量的TIME_WAIT状态的连接,而且并发量越大处于此种状态的连接越多。另外,对于被动关闭连接的服务在主动关闭客户端非法请求或清理长时间不活动的连接时(这种情况很可能是客户端程序忘记关闭连接)也会出现TIME_WAIT的状态。

2.TCP粘包解决的办法

黏包问题是指在传输过程中多个数据包被合并成了一个或者一个数据包被拆分成了多个,造成接收方无法正确解析。解决黏包问题的方法主要有以下两种:

  1. 固定包头接收:发送方在每个数据包前加上固定长度的头部信息,接收方先读取头部信息获取数据包长度,再根据长度截取对应的数据。这样可以保证每次接收到的数据都是完整的。
  2. 指定内存长度:发送方在每个数据包前不添加任何头部信息,而是在尾部添加一个特殊字符(例如换行符“\n”),接收方按照特殊字符进行切割,并且预先给缓存区分配足够长的空间来容纳整个消息。这样也能确保接收到的数据都是完整的。

解决TCP粘包的代码实例:

核心思想:在C++中,处理TCP粘包问题通常涉及到自定义协议来区分数据包。这意味着需要设计一种机制来标记每个数据包的开始和结束。

服务器端:

#include <boost/asio.hpp>  
#include <iostream>  
#include <vector>  
  
using boost::asio::ip::tcp;  
  
class session : public std::enable_shared_from_this<session> {  
public:  
    session(tcp::socket socket) : socket_(std::move(socket)) {}  
  
    void start() {  
        do_read();  
    }  
  
private:  
    void do_read() {  
        auto self(shared_from_this());  
        char buffer[1024];  
  
        socket_.async_read_some(boost::asio::buffer(buffer),  
            [this, self](boost::system::error_code ec, std::size_t length) {  
                if (!ec) {  
                    std::cout.write(buffer, length);  
                    std::cout << std::endl;  
  
                    do_read();  
                }  
            });  
    }  
  
    tcp::socket socket_;  
};  
  
int main(int argc, char* argv[]) {  
    try {  
        if (argc != 2) {  
            std::cerr << "Usage: async_tcp_echo_server <port>\n";  
            return 1;  
        }  
  
        boost::asio::io_context io_context;  
  
        tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), std::atoi(argv[1])));  
  
        for (;;) {  
            tcp::socket socket(io_context);  
            acceptor.async_accept(socket,  
                [&](boost::system::error_code ec) {  
                    if (!ec) {  
                        std::make_shared<session>(std::move(socket))->start();  
                    }  
                });  
        }  
  
        io_context.run();  
    }  
    catch (std::exception& e) {  
        std::cerr << "Exception: " << e.what() << "\n";  
    }  
  
    return 0;  
}

客户端代码:

#include <boost/asio.hpp>  
#include <iostream>  
  
using boost::asio::ip::tcp;  
  
int main(int argc, char* argv[]) {  
    try {  
        if (argc != 3) {  
            std::cerr << "Usage: async_tcp_echo_client <host> <port>\n";  
            return 1;  
        }  
  
        boost::asio::io_context io_context;  
  
        tcp::resolver resolver(io_context);  
        tcp::resolver::results_type endpoints = resolver.resolve(argv[1], argv[2]);  
  
        tcp::socket socket(io_context);  
        boost::asio::connect(socket, endpoints);  
  
        for (int i = 0; i < 5; ++i) {  
            std::string message = "Hello, world! (" + std::to_string(i) + ")\n";  
  
            boost::asio::write(socket, boost::asio::buffer(message));  
        }  
  
        io_context.run();  
    }  
    catch (std::exception& e) {  
        std::cerr << "Exception: " << e.what() << "\n";  
    }  
  
    return 0;  
}

总结:本篇文章描述了C++的常见的一些问题  粘包 时间等待线程  这些在我们的开发中有时候会遇到 我们要积极的解决 否则就会出现很多问题

好了 本篇文章就到这里结束了 在这里我给大家推荐一个性价比很高的课程:

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

相关文章
|
监控 网络协议 NoSQL
五分钟带你读懂 TCP全连接队列(图文并茂)
今天有个小伙伴跑过来告诉我有个奇怪的问题需要协助下,问题确实也很奇怪。客户端调用RT比较高并伴随着间歇性异常Connection reset出现,而服务端CPU 、线程栈等看起来貌似都很正常,而且服务端的RT很短
9271 0
五分钟带你读懂 TCP全连接队列(图文并茂)
|
网络安全 数据安全/隐私保护
为什么免费证书的有效期为90天
为什么免费证书的有效期为90天
1369 0
|
监控 前端开发 JavaScript
AST 代码扫描实战:如何保障代码质量
2020 年 618 大促已经过去,作为淘系每年重要的大促活动,淘系前端在其中扮演着什么样的角色,如何保证大促的平稳进行?又在其中应用了哪些新技术?淘系前端团队特此推出「618 系列|淘系前端技术分享」,为大家介绍 618 中的前端身影。 本篇来自于频道与D2C智能团队的菉竹,为大家介绍本次 618 大促中是如何用代码扫描做资损防控的。
3749 0
AST 代码扫描实战:如何保障代码质量
|
7月前
|
设计模式 人工智能 安全
AQS:Java 中悲观锁的底层实现机制
AQS(AbstractQueuedSynchronizer)是Java并发包中实现同步组件的基础工具,支持锁(如ReentrantLock、ReadWriteLock)和线程同步工具类(如CountDownLatch、Semaphore)等。Doug Lea设计AQS旨在抽象基础同步操作,简化同步组件构建。 使用AQS需实现`tryAcquire(int arg)`和`tryRelease(int arg)`方法以获取和释放资源,共享模式还需实现`tryAcquireShared(int arg)`和`tryReleaseShared(int arg)`。
406 32
AQS:Java 中悲观锁的底层实现机制
|
网络协议 安全 Unix
聊聊TCP中的TIME_WAIT
【4月更文挑战第4天】 TIME_WAIT 的产生、作用以及优化
|
10月前
|
SQL 数据库
数据库数据恢复—SQL Server报错“错误 823”的数据恢复案例
SQL Server数据库附加数据库过程中比较常见的报错是“错误 823”,附加数据库失败。 如果数据库有备份则只需还原备份即可。但是如果没有备份,备份时间太久,或者其他原因导致备份不可用,那么就需要通过专业手段对数据库进行数据恢复。
|
机器学习/深度学习 人工智能 弹性计算
阿里云GPU服务器全解析_GPU价格收费标准_GPU优势和使用说明
阿里云GPU云服务器提供强大的GPU算力,适用于深度学习、科学计算、图形可视化和视频处理等场景。作为亚太领先的云服务商,阿里云GPU云服务器具备高灵活性、易用性、容灾备份、安全性和成本效益,支持多种实例规格,满足不同业务需求。
3019 2
|
NoSQL 关系型数据库 MySQL
基于Redis和MySQL的架构,如何保证数据一致性?
今天分享一道一线大厂公司高频面试题。“基于Redis和MySQL的架构,如何保证数据一致性”。这个问题难倒了不少工作5年以上的程序员,难的不是问题本身,而是解决这个问题的思路。
428 2
|
传感器 算法 Ubuntu
大疆M2006电机测试文档
本文是关于大疆RoboMaster M2006电机的测试文档,介绍了在Ubuntu20.04环境下通过ROS读取电机反馈信息、控制电机移动,并利用PID控制算法实现速度闭环的测试流程,涵盖了测试材料、接线方法、电机校准、CAN通讯测试以及在ROS中的移植和PID调节的详细步骤和方法。
1323 0
大疆M2006电机测试文档
|
机器学习/深度学习 人工智能 数据可视化
号称能打败MLP的KAN到底行不行?数学核心原理全面解析
Kolmogorov-Arnold Networks (KANs) 是一种新型神经网络架构,挑战了多层感知器(mlp)的基础,通过在权重而非节点上使用可学习的激活函数(如b样条),提高了准确性和可解释性。KANs利用Kolmogorov-Arnold表示定理,将复杂函数分解为简单函数的组合,简化了神经网络的近似过程。与mlp相比,KAN在参数量较少的情况下能达到类似或更好的性能,并能直观地可视化,增强了模型的可解释性。尽管仍需更多研究验证其优势,KAN为深度学习领域带来了新的思路。
6061 5