udp/tcp错误总结

udp
tcp——多进程
tcp——多线程
tcp——线程池
tcp——守护进程

🎆udp
 ✨pthread_create 错误总结
 ✨LockGuard错误总结
 ✨服务端需要写成多线程
 ✨客户端也需要写成多线程
 ✨多线程调试工具
🎆tcp
 ✨tcp独有调试工具——telnet
 ✨ThreadPool —— 短连接
 ✨pthread_create —— 长连接
 ✨fork——长连接
 ✨进程池版的守护进程

在这里插入图片描述

🎆udp

✨1. pthread_create 错误总结

    static void* Routine(void* argv)
    {
        // 线程本身就是运行起来一次就要结束,结束的动作由外部执行
        Thread* th = static_cast<Thread*>(argv);
        th->_fun(th->_info);// 线程自动调用这个函数,并将参数传递过去
        return nullptr;
    }
    bool Start()
    {
        cout << _name ;
        puts(" 线程将要运行");
        int n = pthread_create(&_tid,nullptr,Routine,this);
        cout << _name;
        puts(" 线程已经运行");
        if(n)
            return false;
        return true;
    }

pthread_create 不能使用 bind 进行绑定,只能使用static 函数进行创建

✨2. LockGuard错误总结

class LockGuard
{
public:
    // 锁必须传指针,不能传值/引用
    // 传值/引用会造成死锁现象
    LockGuard(const std::string& func_name, pthread_mutex_t* mtx):_func_name(func_name),_mutex(mtx)
    {
        // puts("上锁");
        std::cout << "LockGuard:" <<  _func_name << "上锁" << std::endl;
        pthread_mutex_lock(_mutex);// 死锁位置
        // puts("上锁完成");
        std::cout << "LockGuard:" <<  _func_name << "上锁完成" << std::endl;

    }
    ~LockGuard()
    {
        // puts("开始解锁");
        std::cout << "LockGuard:" << _func_name << "解锁" << std::endl;
        pthread_mutex_unlock(_mutex);
        // puts("解锁完成");

    }
private:
    // pthread_mutex_t _mutex = PTHREAD_MUTEX_INITIALIZER;// 这个锁不能初始化,这个锁用的是外面的锁
    pthread_mutex_t* _mutex;
    std::string _func_name;
};

​ 必须使用传指针的方式,如果使用传引用/传值的方式,就会出现死锁

✨3. 服务端需要写成多线程

如果写成单线程,可能会出现服务端只为一个服务,另一个发送消息显示不出来的情况;当此连接释放才能将内容显示出来

✨4. 客户端也需要写成多线程

需要一个send线程,一个recv线程
如果只有一个线程,线程如果阻塞在send线程,也就是需要从标准输入中读取才能进行发送,那么就无法进行recv;由于udp有自己的缓冲区,所以即使无法运行recv也是可以将少量消息进行记录

✨5. 多线程调试工具

pstack —— 查看多进程函数栈
gdb attach 线程id
info threads——查看线程信息
t 线程编号——切换线程
info b——查看线程信息

详细请参考 多进程调试工具

🎆tcp

✨tcp独有调试工具——telnet

没有写客户端的情况下还想进行调试,可以使用telnet进行调试,telnet只能对tcp进行使用

ThreadPool —— 短连接

  1. 什么是短连接
    长连接:将一个接收和发送作为一个任务,一个线程一直做这一个工作,知道客户端关闭,线程结束
    短连接:将一个接收和发送作为一个任务,一个套接字执行一个任务之后立即释放

  2. 理解为什么TheadPool 模型必须使用短连接
    线程池中线程个数有限如果使用长连接,服务端只能接收有限的用户,很显然是不合理的

  3. 使用function包装函数类型不同头文件中可能出现函数类型重名的问题
    在这里插入图片描述

  4. 灵活规定ThreadPool的任务类型
    在这里插入图片描述
    问题一为什么ThreadPool的类型是Task,为什么不能是一个套接字或者别的
    首先我们要明确线程要执行的任务是:使用套接字进行接收+发送消息
    问题二accept 函数是在主线程or子线程
    肯定是在主线程中,如果在子线程中还需要考虑访问套接字冲突的问题
    所以传递套接字应该是传递的接收消息的套接字
    问题三:为什么要将执行函数封装进去,可不可以在Task类中进行执行
    在Task类中实现执行函数完全是OK的,最关键的一点是要在Task类中重载(),这样在使用的时候就可以像执行函数一样执行了
    在这里插入图片描述

注意:在子线程中,执行完一个任务需要将这个任务的接收消息的套接字关闭,防止资源消耗完
在这里插入图片描述

pthread_create —— 长连接

  1. 一定要明确变量是要被外部使用还是只在本作用域中使用
    在这里插入图片描述
    如果局部变量需要传给外部进行使用,并且接收的参数是指针,当外部进行使用的时候,当前空间已经被回收,就无法拿到原来的数据
    解决方法:
    方法一:将接收参数改为传值接收
    方法二传递堆空间
  2. 创建子线程需要进行分离每个子线程使用的是不同的描述套接字,所以不存在访问冲突的问题,不需要加锁
    在这里插入图片描述

fork——长连接

  1. 因为进程有很强的独立性,所以可以将接收数据的套接字写成成员变量;父子进程间会发生写实拷贝,所有每个进程都会独立的维护自己的接收数据的套接字,完全不用担心在接收到一个全新的的连接之后会将上一个接收数据的套接字进行覆盖的情况
    在这里插入图片描述
  2. 满满的细节
    细节一子进程需要关闭父进程中的接收连接的套接字文件描述符——防止文件描述符的消耗
    细节二:为了不让父进程等待子进程退出,使用孙子进程的方式解决;子进程会立即结束,父进程也会立即回收子进程并等待下次连接
    细节三孙子进程连接结束一定要关闭文件描述符;首先关闭文件描述符是一个好习惯,其次文件描述符是使用引用计数的方式实现的,子进程退出,系统会自动回收子进程的资源,包括文件描述符,虽然在代码中没有什么危险,但是还是要关注这个细节
    细节四:虽然孙子进程会自动被系统回收,但是孙子进程也是需要手动退出,如果孙子进程没有主动退出,那么它将和父进程一样等待下次的连接
    在这里插入图片描述

✨进程池版的守护进程

  1. 手写守护进程
    SIGCLD, SIGPIPE, SIGSTOP 忽略——这三个信号在发出后,系统需要进行处理,需要从用户态转变为内核态,这个过程是很消耗资源,为了防止这种消耗,就将这三个信号进行忽略,并且这中操作在守护进程中是很常见的
    使用setsid来创建守护进程
    并将标准输入,标准输出,标准错误重定向到/dev/null文件中,/dev/null这个文件的内容会被自动丢掉,就像垃圾桶一样
    在这里插入图片描述
  2. 如果线程池先创建出来,再创建守护进程,那么守护进程不会将父进程中的线程继承下来,就导致了守护进程中虽然能将任务push进线程池,但是线程池中根本没有线程能够完成任务
    在这里插入图片描述
    所以根据他使用的时候创建的特点我们想到可以使用懒汉模式——完美解决守护进程无法继承父进程的线程的问题
    在这里插入图片描述还要注意懒汉模式是有线程安全问题,需要双层保障

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/579739.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python的历史演变与作用

目录 1.概述 2.起源 3.发展阶段 4.Python 3的诞生 5.现状与未来 6.Python的作用 6.1.Web开发 6.2.数据科学与人工智能 ​​​​​​​6.3.自动化与脚本编程 ​​​​​​​6.4.教育与学习 ​​​​​​​6.5.其他领域 7.结语 1.概述 Python&#xff0c;一门富有表…

DSP开发实战教程-国产DSP替代进口TI DSP的使用技巧

1.替换CCS安装路径下的Flash.out文件 找到各自CCS的安装路径&#xff1a; D:\ti\ccs1230\ccs\ccs_base\c2000\flashAlgorithms 复制进芯电子国产DSP官网提供的配置文件 下载链接&#xff1a;https://mp.csdn.net/mp_download/manage/download/UpDetailed 2.替换原有文件 3.…

Thinkphp--in-sqlinjection

一、漏洞原理 在 Builder 类的 parseData 方法中&#xff0c;由于程序没有对数据进行很好的过滤&#xff0c;将数据拼接进 SQL 语句&#xff0c;导致 SQL注入漏洞 的产生。 影响版本 5.0.13<ThinkPHP<5.0.15 5.1.0<ThinkPHP<5.1.5 在相应的文件夹位置打开终端…

记录如何用php做一个网站访问计数器的方法

简介 创建一个简单的网站访问计数器涉及到几个步骤&#xff0c;包括创建一个用于存储访问次数的文件或数据库表&#xff0c;以及编写PHP脚本来增加计数和显示当前的访问次数。 方法 以下是使用文件存储访问次数的基本步骤&#xff1a; 创建一个文本文件来存储计数&#xff1a…

.NET 检测地址/主机/域名是否正常

&#x1f331;PING 地址/主机名/域名 /// <summary>/// PING/// </summary>/// <param name"ip">ip</param>/// <returns></returns>public static bool PingIp(string ip){System.Net.NetworkInformation.Ping p new System.N…

Codeforces Round 941 (Div. 1) E. Connected Cubes(构造)

题目 思路来源 官方题解 题解 可以看下官方题解的7张图&#xff0c;还是比较清晰的&#xff0c;这里直接粘贴一下 来源&#xff1a;Codeforces Round #941 (Div. 1, Div. 2) Editorial - Codeforces &#xff08;1&#xff09;原来的图 &#xff08;2&#xff09;对于偶数行…

牛客NC376 变回文串的最少插入次数【困难 动态规划,回文 C++/Java/Go/PHP 高频】力扣同一道题1312

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/bae2652b4db04a438368238498e4c13e https://leetcode.cn/problems/minimum-insertion-steps-to-make-a-string-palindrome/description/ 思路 参考答案C class Solution {public:/*** 代码中的类名、方法名、参…

炒股自动化:券商官方,散户可用,查询订单状态API如何用?

券商官方的接口&#xff0c;个人账户可申请&#xff0c;入金门槛低&#xff0c;接入文档完善&#xff0c;技术支持好的&#xff0c;经过我们筛选后&#xff0c;只有一家符合 会编程&#xff0c;有基础&#xff0c;只是需要API接口的朋友不用看这些&#xff0c;不会写程序的朋友…

nacos-redis-springboot

新项目 准备工作 nacos 版本 2.0.3 redis 最终版本说明 springcloud-alibaba&#xff1a;2.2.7RELEASE springcloud&#xff1a;Hoxton.SR12 springboot&#xff1a;2.3.12.RELEASE Nacos&#xff1a;2.0.3 步骤 启动nacos和redis 准备nacos配置文件 server: port…

avl excite python二次开发1--python解释器需用内置解释器aws_cmd

avl excite python二次开发1--python解释器需用内置解释器aws_cmd 1、python解释器问题1.1、用外置python解释器&#xff0c;import WSInterface会失败(WSInterface.pyd)1.2、用内置解释器aws_cmd运行py脚本1.3 用内置解释器aws_python执行脚本三级目录 1、python解释器问题 1…

ssm项目后端如何导出war及前端如何导出静态资源

后端如何导出war包 后端工具&#xff1a;IDEA 2020.1.3 运行我们编写工具maven里面的package 运行成功的日志 我们运行完&#xff0c;会生成一个target文件夹&#xff0c;在这个文件夹里面找到war包即可 前端如何导出静态资源 使用工具&#xff1a;WebStorm 2020.1.3 打开左…

xLua详解

目录 环境准备xLua导入 C#调用LuaLua解析器Lua文件加载重定向Lua解析管理器全局变量的获取全局函数的获取List和Dictionary映射table类映射table接口映射tableLuaTable映射table Lua调用C#准备工作Lua使用C#类Lua调用C#枚举Lua使用C# 数组 List 字典数组List字典 Lua使用C#扩展…

读天才与算法:人脑与AI的数学思维笔记12_数学的艺术

1. 数学 1.1. 灵光乍现&#xff0c;从来都是厚积薄发 1.1.1. 亨利庞加莱&#xff08;Henri Poincar&#xff09; 1.2. 数学的起源可以追溯到人类试图理解自己所生活的环境&#xff0c;预测接下来会发生什么&#xff0c;从而使我们更加适应环境&#xff0c;并选择对我们有利的…

Python-VBA函数之旅-map函数

目录 一、map函数的常见应用场景 二、map函数使用注意事项 三、如何用好map函数&#xff1f; 1、map函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a;神奇夜光杯-CSDN博客 一、map函数的常见应用场景 ma…

Jammy@Jetson Orin - Tensorflow Keras Get Started: Concept

JammyJetson Orin - Tensorflow & Keras Get Started: Concept 1. 源由2. 模型2.1 推理流程2.1.1 获取图像2.1.2 算法识别2.1.3 判断决策 2.2 理想情况2.2.1 多因素输入2.2.2 理想识别概率 2.3 学习过程2.3.1 标记训练集2.3.2 损失函数2.3.3 训练网络2.3.4 渐进方法 3. 总…

使用Docker部署Jupyter Notebook并结合花生壳的内网穿透实现远程访问(详文)

一、前言 本文主要介绍如何利用宝塔面板中的Docker 3.9.3管理器,使用Docker本地部署Jupyter Notebook,并结合花生壳内网穿透工具实现任意浏览器公网远程访问Jupyter登录界面。 安装完成后在宝塔面板中图例 Jupyter Notebook是一个交互式笔记本,支持运行40多种编程语言。…

Vue 组件单元测试深度探索:组件交互与状态变更 专业解析和实践

在Vue组件单元测试中&#xff0c;验证组件之间的交互&#xff08;如父组件与子组件、兄弟组件之间的通信&#xff09;以及状态变更的正确性对于保证整个应用的协调运作至关重要。本文详细介绍了父组件向子组件传递props、子组件向父组件发送事件、兄弟组件通过共享状态&#xf…

xfce4 panel 不能显示QQ,钉钉的状态图标

有一段时间不能显示了&#xff0c;之前刚装完系统的时候很长时间内都是好的&#xff0c;所以刚开始肯定是支持显示这些状态图标的。就是因为不能显示的原因&#xff0c;所以还装了lxQt桌面&#xff0c;这个桌面确实不错。不过还是有时会怀念xfce4&#xff0c;想看看能不能解决这…

Odoo:全球排名第一的免费开源PLM管理系统介绍

概述 利用开源智造OdooPLM产品生命周期管理应用&#xff0c;重塑创新 实现产品生命周期管理数字化&#xff0c;高效定义、开发、交付和管理创新的可持续产品&#xff0c;拥抱数字化供应链。 通过开源智造基于Odoo开源技术平台打造数字化的产品生命周期管理&#xff08;PLM&am…

Java UUID 类中的 getMostSignificantBits 和 leastSignificantBits 方法

getMostSignificantBits() 方法的一些介绍&#xff1a; getMostSignificantBits 这个方法主要用于在 UUID 中获取高64 位的有效位后返回 Long 数据类型。 在获取最高有效位时不会引发异常。 对应的还有一个 getLeastSignificantBits() 方法。 这个方式是从 UUID 中获取低 6…
最新文章