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

相关文章
|
消息中间件 网络协议 物联网
MQTT常见问题之物联网设备端申请动态注册时MQTT服务不可用如何解决
MQTT(Message Queuing Telemetry Transport)是一个轻量级的、基于发布/订阅模式的消息协议,广泛用于物联网(IoT)中设备间的通信。以下是MQTT使用过程中可能遇到的一些常见问题及其答案的汇总:
|
监控 网络协议 NoSQL
五分钟带你读懂 TCP全连接队列(图文并茂)
今天有个小伙伴跑过来告诉我有个奇怪的问题需要协助下,问题确实也很奇怪。客户端调用RT比较高并伴随着间歇性异常Connection reset出现,而服务端CPU 、线程栈等看起来貌似都很正常,而且服务端的RT很短
五分钟带你读懂 TCP全连接队列(图文并茂)
|
存储 安全 Linux
linux系统中u-boot命令的EMMC和SD卡操作命令分析
linux系统中u-boot命令的EMMC和SD卡操作命令分析
1198 1
|
人工智能 数据安全/隐私保护 计算机视觉
GitHub爆款神器 | IOPaint:21.7k star 开源AI图像修复项目,竟能秒删水印、拓展画幅!
IOPaint 是一款由 Sanster 团队开发的开源图像处理工具,集成多种 SOTA AI 模型,支持图像擦除、对象替换、文本绘制和图像外扩等功能。它操作简便,一键安装,适用于 Windows、macOS、Linux 和 Apple Silicon 系统,适合摄影爱好者、电商从业者及内容创作者使用,大幅提升图像处理效率。
124 0
|
网络协议 安全 Unix
聊聊TCP中的TIME_WAIT
【4月更文挑战第4天】 TIME_WAIT 的产生、作用以及优化
|
6月前
|
安全 Java C#
使用try-with-resources实现自动解锁
本文介绍了如何利用Java的`try-with-resources`语法糖实现Redission分布式锁的自动解锁。通过将锁包装为实现了`AutoCloseable`接口的类,在`try`语句块结束时自动释放锁,简化了锁管理,避免了手动解锁的繁琐和潜在错误。示例代码展示了具体的实现方法,并分析了其优点和注意事项。这种模式提高了代码的简洁性、可靠性和可维护性,特别适用于多线程编程中的并发控制。
122 5
|
7月前
|
SQL 数据库
数据库数据恢复—SQL Server报错“错误 823”的数据恢复案例
SQL Server数据库附加数据库过程中比较常见的报错是“错误 823”,附加数据库失败。 如果数据库有备份则只需还原备份即可。但是如果没有备份,备份时间太久,或者其他原因导致备份不可用,那么就需要通过专业手段对数据库进行数据恢复。
|
缓存 负载均衡 网络协议
Linux的TCP连接数量与百万千万并发应对策略
【8月更文挑战第15天】在Linux系统中,关于TCP连接数量的一个常见误解是认为其最大不能超过65535个。这一数字实际上是TCP端口号的上限,而非TCP连接数的直接限制。实际上,Linux服务器能够处理的TCP连接数远远超过这一数字,关键在于理解TCP连接的标识方式、系统配置优化以及应用架构设计。
1175 2
|
NoSQL 关系型数据库 MySQL
基于Redis和MySQL的架构,如何保证数据一致性?
今天分享一道一线大厂公司高频面试题。“基于Redis和MySQL的架构,如何保证数据一致性”。这个问题难倒了不少工作5年以上的程序员,难的不是问题本身,而是解决这个问题的思路。
405 2
|
NoSQL Redis 数据库
docker-compose 自动管理 数据库
docker-compose 自动管理 数据库
430 3