muduo库的初步认识和基本使用,创建一个简单查询单词服务系统
小编在学习完muduo库之后,觉得对于初学者,muduo库还是有点不好理解,所以在此,小编来告诉大家muduo库的初步认识和基本使用,让初学者也可以更快的上手和使用muduo库。
一、muduo的初步认识
1、对TcpServer.h的初步认识
这张图片告诉大家muduo库的构造函数,让我来解释一下没给参数的概念及意思。
a.EventLoop* loop 是TcpServer的事件循环监控,它是一个死循环,大家知道多路转接的时候需要一个事件循环监控,来告诉我们那个事件已经就绪,然后我们来进行对这个事件的操作,所以这个loop就是来做这个事情的,后面我们会介绍这个 loop的头文件,不着急。
b.const InetAddress& listenAddr 储存的是TcpServer监听的ip地址和端口号,TcpServer要进行启动,必须有一个可以被外部连接的ip和端口号才可以。
c.const string& nameArg 是你这个TcpServer服务的名字,这个就是自己对自己的服务起一个名字。
d.Option option = kNoReusePort 是一个选项,告诉操作系统是否要开启地址复用,他的选项 第一个KNoReusePort是不开启地址复用,第二个KReusePort是开启地址复用。
2、对TcpServer.h中其他重要函数的认识
这个函数是TcpServer.h中必须要进行设置的函数,这个函数的意思是我们接收到外部的连接后需要调用的回调函数,可能到这里大家还不知道有啥用,先不着急,继续往后看。
这个函数也是TcpServer.h中必须要设置的函数,这个函数的意思是我们进行事件监控之后,收到外部发来的消息需要对消息进行的处理回调函数,也是继续往后看。
这个函数是开启TcpServer服务
3、对EventLoop.h的认识
构造函数没有参数,直接无参构造就好。
这个函数来直接启动事件循环操作,内部是一个死循环。
4、对TcpClient.h的认识
还是一样,让我来告诉大家这个TcpClient的构造函数的参数意思。
a.EventLoop* loop 和TcpServer构造函数中的意思一样,但是有个不一样的地方是在TcpClient中不能让TcpClient是一个死循环,因为EventLoop是一个死循环,因为客户端要进行对服务端发送消息,不能让事件循环监控是一个死循环,这样客户端就不能往下执行了,只能一直对事件进行循环监控,后面使用一下大家也就会了。
b. const InetAddress& serverAddr 的意思客户端要访问的服务端的ip和端口号。
c.const string& nameArg 的意思和服务端的意思一样,也就是给客户端起一个名字。
5、对TcpClient.h中重要的函数的认识
这个函数的意思是对客户端连接服务端之后调用的回调函数,这个函数也必须要设置。
这个函数的意思是客户端进行事件监控之后,收到消息之后,调用的对消息处理的回调函数,也必须要设置。
这个函数的意思是对服务端进行连接,连接之后直接自己启动客户端的操作。
6、对TcpConnection.h的认识
这个类比较特别,不需要我们对它进行手动设置参数,它是我们客户端连接到服务端之后,服务端和客户端会创建一个TcpConnection来保存客户端和服务端的信息,包括客户端和服务端的端口号和ip地址,为两端进行通信创建条件。
这个send的接口就是我们进行通信的基础,虽然这个函数有三个重载函数,但是他们的效果都是一样的,都是向对方发送信息报文。
这两个接口告诉我们两端是否连接成功,connected接口告诉我们两端是否连接正常,disconnected反之。
7、对Buffer.h的认识
这个类也就是muduo库自己设置的缓冲区,方便我们对双方的消息进行处理和保存的类,这个类也不需要我们自己进行设置,他自己会进行设置,所以这里的构造函数的参数不需要我们自己管理,在这里我也就不说啦。
8、对Buffer.h中重要函数的认识
这些函数接口都是对Buffer缓冲区进行的读取数据的操作,retrieve接口虽然有很多,但是他们的操作方式都一样,这里咱们以个别为例,retrieveInt64() 这个接口要读取64字节的数据,并且读取完成之后,会把这64字节的数据清空,很好理解,就是读取走缓冲区中的数据,其他的也都一样。还有retrieveAllAsString() 这个接口是用来读取Buffer缓冲区中的所有数据并把它当作一个字符串,也很好理解吧。其他的也都类似,这里就不做讲解了。
9、对EventLoopThread.h的认识
这个类和EventLoop的类功能相似,都是对事件进行循环监控,但是这个类是用开辟一个线程帮我们进行循环监控,这样我们主线程就可以做自己想做的事情了,也就是我们客户端需要用到的这个事件循环监控,因为客户端不可以被阻塞到事件循环监控那块。这个构造函数里面的参数也不用我们用户自己传,所以在这里我也不再讲解。
10、对EventLoopThread.h中重要函数的理解
这个函数来告诉我们它的EventLoop的指针,因为它的底层也是事件循环监控EventLoop。
11、对CountDownLatch.h的认识
这个类协助我们对客户端正确性进行维护,因为客户端在进行连接之后就会自动开始对服务端发送报文,但是如果客户端没有连接到服务端就对服务端发送消息,这不就出错了吗,所以在这里才有了这个类,这个构造函数传的count就是一个数字,当这个数字减为0,就唤醒阻塞,如果这个数字大于0就一直阻塞住,不让客户端发送消息给服务端,可能有点不理解,后面看例子一下子就明白。
12、对CountDownLatch.h中重要函数的理解
这个wait函数一直进行阻塞,countDown函数每次调用就对构造函数中的count进行-1操作,直到减为0,就唤醒wait操作,还是和上面一样,一看例子就明白。
二、基本使用muduo库,创建一个简单的单词查询系统
1、首先我们先看服务端的实现及其代码和注释来理解
class dictServer
{
public:dictServer():_dictserver(&_loop, muduo::net::InetAddress("0.0.0.0", 9090),"dictserver", muduo::net::TcpServer::Option::kReusePort) // 最后一个参数的意思是是否开启地址复用{// 设置这几个必须要的函数_dictserver.setConnectionCallback(std::bind(&dictServer::connectionCallBack, this, std::placeholders::_1));_dictserver.setMessageCallback(std::bind(&dictServer::messageCallBack, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));// 给字典插入数据 随便插入几个单词进行test实验_dictmap["hello"] = "你好";_dictmap["world"] = "世界";_dictmap["apple"] = "苹果";}void running(){// 启动tcp服务和事件循环监控loop服务_dictserver.start();_loop.loop();}~dictServer(){}
private:void connectionCallBack(const muduo::net::TcpConnectionPtr& conn){// 判断是否连接成功if(conn->connected()){std::cout << "连接成功!" << std::endl;}else{std::cout << "连接失败!" << std::endl;}}void messageCallBack(const muduo::net::TcpConnectionPtr& conn, muduo::net::Buffer* buf, muduo::Timestamp time){// 取出来buf里面的数据 进行查询 因为我们没有定制其他协议 这里如果收到客户端发来的一个单词直接全部取出来进行操作std::string str = buf->retrieveAllAsString();// 对这个单词进行查询auto it = _dictmap.find(str);std::string msg;if(it != _dictmap.end()){// 找到了数据msg = (*it).second;}else{msg = "None";}// 把查询到的数据发送给客户端conn->send(msg);}
private:// 因为需要现有 eventloop对象才可以初始化tcpserver对象 所以eventloop对象应在tcpserver上面 这样初始化列表才会正确muduo::net::EventLoop _loop;muduo::net::TcpServer _dictserver;std::unordered_map<std::string, std::string> _dictmap;
};int main()
{dictServer dict;// 启动服务端dict.running();return 0;
}
2、我们来看客户端的实现及其代码和注释来理解
class dictclient
{
public:dictclient()// 这里直接获取EventThreadLoop的指针给EventLoop对象:_loop(_loopthread.startLoop()) // loophtread 开始创建了对象之后 就可以自己在线程中自己循环监控数据, _client(_loop, muduo::net::InetAddress("127.0.0.1", 9090), "dictclient"),_downlatch(1) // 这里的count我们设置为一, 如果连接上就给count--,直接唤醒wait操作,让客户端来进行通信{// 设置这两个必须设置的函数对象_client.setConnectionCallback(std::bind(&dictclient::connCallBack, this, std::placeholders::_1));_client.setMessageCallback(std::bind(&dictclient::mesCallBack, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));_client.connect(); // 这里只是发起了客户端连接服务端的操作_downlatch.wait(); // 用CountDownLatch的类来对客户端进行保护阻塞操作}bool send(const std::string& mes){if(_conn->connected()){// 连接建立成功 可以发送消息_conn->send(mes);return true;}return false;}~dictclient() {}
private:void connCallBack(const muduo::net::TcpConnectionPtr &conn){if (conn->connected()){std::cout << "连接成功!" << std::endl;_conn = conn; // 把这个conn给到自己_downlatch.countDown(); // 让计数器减减 唤醒阻塞client}else{std::cout << "连接失败!" << std::endl;_conn.reset(); // 释放这个指针指向的空间}}void mesCallBack(const muduo::net::TcpConnectionPtr &conn, muduo::net::Buffer *buf, muduo::Timestamp timestamp){// 取出来buf里面的数据 进行查询std::string str = buf->retrieveAllAsString();std::cout << str << std::endl;}private: muduo::net::TcpConnectionPtr _conn; // 因为客户端无法自己访问连接完毕之后创建的TcpConnection对象,所以在此我们进行手动设置一个这个对象muduo::CountDownLatch _downlatch;muduo::net::EventLoopThread _loopthread;muduo::net::EventLoop* _loop;muduo::net::TcpClient _client;
};int main()
{dictclient client;while(true){std::string mes;std::cin >> mes;client.send(mes);}return 0;
}
以上就是我们今天学习的所有内容,如果有什么不理解的地方,大家可以评论区留言或者私信我,我给大家答疑!下期再见啦!
相关文章:

muduo库的初步认识和基本使用,创建一个简单查询单词服务系统
小编在学习完muduo库之后,觉得对于初学者,muduo库还是有点不好理解,所以在此,小编来告诉大家muduo库的初步认识和基本使用,让初学者也可以更快的上手和使用muduo库。 Muduo由陈硕大佬开发,是⼀个基于 非阻塞…...
电脑如何保养才能用得更久
在这个数字化的时代,电脑已经成为了我们生活和工作中不可或缺的伙伴。无论是处理工作文档、追剧娱乐,还是进行创意设计,电脑都发挥着至关重要的作用。那么,如何让我们的电脑“健康长寿”,陪伴我们更久呢?今…...
Oracle的NVL函数
Oracle的NVL函数是一个常用的空值处理函数,主要用于在查询结果中将NULL值替换为指定的默认值。以下是关于NVL函数的详细说明: 基本语法 NVL(expr1, expr2) 如果expr1为NULL,则返回expr2如果expr1不为NULL,则返回expr1本身 …...

【HTML/CSS面经】
HTML/CSS面经 HTML1. script标签中的async和defer的区别2. H5新特性(1 标签语义化(2 表单功能增强(3 音频和视频标签(4 canvas和svg绘画(5 地理位置获取(6 元素拖动API(7 Web Worker(…...

git查看commit属于那个tag
1. 快速确认commit原始分支及合入tag # git describe 213b4b3bbef2771f7a1b8166f6e6989442ca67c8 查看commit合入tag # git describe 213b4b3bbef2771f7a1b8166f6e6989442ca67c8 --all 查看commit原始分支 2.查看分支与master关系 # git show --all 0.5.67_0006 --stat 以缩…...
如何从ISO镜像直接制作Docker容器基础镜像
引言 这段最值得总结的经验知识,就是如何在ISO镜像的基础上,直接做出docker base image,无需联网! 特别地,对于一些老旧OS系统,都能依此做出docker base image! 例如,某些老旧系统,CentOS 6,…...
网站缓存入门与实战:浏览器与Nginx/Apache服务器端缓存,让网站速度起飞!(2025)
更多服务器知识,尽在hostol.com 嘿,各位站长和网站管理员朋友们!咱们精心打造的网站,内容再好,设计再炫,如果用户打开它的时候,加载速度慢得像“老牛拉破车”,那体验可就大打折扣了…...

mysql-mysql源码本地调试
前言 先进行mysql源码本地编译:mysql源码本地编译 1.本地调试 这里以macbook为例 1.使用vscode打开mysql源码 2.创建basedir目录、数据目录、配置文件目录、配置文件 cd /Users/test/ mkdir mysqldir //创建数据目录和配置目录 cd mysqldir mkdir conf data …...

PCIe— Legacy PCI
Legacy Model 该器件通过将其引脚置位到控制器来生成中断。 在较旧的系统中,这个控制 器通常是Intel 8259 PIC,有15个IRQ输入和一个INTR输出。 然后,PIC将断 言INTR以通知CPU一个或多个中断正在挂起。 一旦CPU检测到INTR的断言…...

PostgreSQL数据库配置SSL操作说明书
背景: 因为postgresql或者mysql目前通过docker安装,只需要输入主机IP、用户名、密码即可访问成功,这样其实是不安全的,可能会通过一些手段获取到用户名密码导致数据被窃取。而ES、kafka等也是通过用户名/密码方式连接,…...
MySQL 的 super_read_only 和 read_only 参数
MySQL 的 super_read_only 和 read_only 参数 一、参数基本概念 1. read_only 参数 作用:控制普通用户是否只能读取数据影响范围:所有非SUPER权限的用户默认值:OFF(可读写) 2. super_read_only 参数 作用…...

低碳理念在道路工程中的应用-预制路面
一、引子 在上一篇文章里,给大家介绍了预制基层的应用,有人提出,既然基层能够预制,那么,道路面层能不能预制呢,有没有相关的研究成果和应用实例呢?答案是肯定的,在本篇文章中&#x…...

12-后端Web实战(登录认证)
在前面的课程中,我们已经实现了部门管理、员工管理的基本功能,但是大家会发现,我们并没有登录,就直接访问到了Tlias智能学习辅助系统的后台。 这是不安全的,所以我们今天的主题就是登录认证。最终要实现的效果是&#…...
TIDB创建索引失败 mkdir /tmp/tidb/tmp_ddl-4000/1370: no such file or directory.
TIDB创建索引失败:解决“mkdir /tmp/tidb/tmp_ddl-4000/1370: no such file or directory”问题 在使用 TIDB 数据库时,我们有时会遇到创建索引失败的问题。常见的错误信息为: mkdir /tmp/tidb/tmp_ddl-4000/1370: no such file or directo…...
Redis 插入中文乱码键
Java 代码: Bean// 静态代理模式: Redis 客户端代理类增强public StringRedisTemplateProxy stringRedisTemplateProxy(RedisKeySerializer redisKeySerializer,StringRedisTemplate stringRedisTemplate,RedissonClient redissonClient) {stringRedisTemplate.setK…...
Mac OS 使用说明
Mac 的启动组合键 了解可通过在启动时按住一个或多个按键来访问的 Mac 功能和工具。 若要使用这些组合键中的任何一个,请在按下电源按钮以开启 Mac 后或在 Mac 开始重新启动后,立即按住相应按键。请一直按住,直至电脑出现对应的行为。 !!!上…...

4.2.2 Spark SQL 默认数据源
在本实战概述中,我们探讨了如何在 Spark SQL 中使用 Parquet 格式作为默认数据源。首先,我们了解了 Parquet 文件的存储特性,包括其二进制存储方式和内嵌的 Schema 信息。接着,通过一系列命令,我们演示了如何在 HDFS 上…...

234. Palindrome Linked List
目录 一、题目描述 方法一、使用栈 方法二、将链表全部结点值复制到数组,再用双指针法 方法三、递归法逆序遍历链表 方法四、快慢指针反转链表 一、题目描述 234. Palindrome Linked List 方法一、使用栈 需要遍历两次。时间复杂度O(n),空间复杂度…...
广州邮科高频开关电源:以创新科技赋能通信能源绿色未来
在数字化浪潮席卷全球的当下,通信网络作为信息社会的基石,其稳定运行对电源系统的可靠性、效率及智能化水平提出了更高要求。作为国内通信电源领域的领军企业,广州邮科凭借其自主研发的高频开关电源技术,以高效节能、智能管控、绿…...
day41 python图像识别任务
目录 一、数据预处理:为模型打下坚实基础 二、模型构建:多层感知机的实现 三、训练过程:迭代优化与性能评估 四、测试结果:模型性能的最终检验 五、总结与展望 在深度学习的旅程中,多层感知机(MLP&…...

无人机报警器探测模块技术解析!
一、运行方式 1. 频谱监测与信号识别 全频段扫描:模块实时扫描900MHz、1.5GHz、2.4GHz、5.8GHz等无人机常用频段,覆盖遥控、图传及GPS导航信号。 多路分集技术:采用多传感器阵列,通过信号加权合并提升信噪比,…...
Docker 替换宿主与容器的映射端口和文件路径
在使用 Docker 容器化应用程序时,经常需要将宿主机的端口和文件路径映射到容器中,以便在本地访问容器中的服务和数据。本文将详细介绍如何替换和配置 Docker 容器的端口和文件路径映射。 1. 端口映射 端口映射用于将宿主机的端口转发到容器中的端口&am…...
我的3种AI写作节奏搭配模型,适合不同类型写作者
—不用内耗地高效写完一篇内容,原来可以这样搭配AI ✍️ 开场:为什么要“搭配节奏”写作? 很多人以为用AI写作,就是丢一句提示词,然后“等它写完”。 但你有没有遇到这些情况: AI写得很快,学境…...

Bonjour
Bonjour 是苹果的一套零配置网络协议,用于发现局域网内的其他设备并进行通信,比如发现打印机、手机、电视等。 一句话:发现局域网其他设备和让其他设备发现。 Bonjour 可以完成的工作 IP 获取名称解析搜索服务 实际应用场景示例࿰…...

华为云Flexus+DeepSeek征文 | 基于Dify和DeepSeek-R1开发企业级AI Agent全流程指南
作者简介 我是摘星,一名专注于云计算和AI技术的开发者。本次通过华为云MaaS平台体验DeepSeek系列模型,将实际使用经验分享给大家,希望能帮助开发者快速掌握华为云AI服务的核心能力。 目录 1. 前言 2. 环境准备 2.1 华为云资源准备 2.1 实…...

HarmonyOS-ArkUI固定样式弹窗(1)
固定样式弹窗指的就是ArkUI中为我们提供的一些具备界面模板性质的弹窗。样式是固定的,我们可以决定在这些模板里输入什么样的内容。常见的有,警告弹窗, 列表选择弹窗, 选择器弹窗,对话框,操作菜单。 下图是本文中要讲到的基类固定样式弹窗,其中选择器弹窗没有包含在内,…...

痉挛性斜颈相关内容说明
一、颈部姿态的异常偏移 痉挛性斜颈会打破颈部原本自然笔直的状态,让颈部像被无形的力量牵引,出现不自主的歪斜、扭转。它就像打乱了颈部原本和谐的 “平衡游戏”,使得颈部姿态偏离正常,影响日常的体态与活动。 二、容易察觉…...
C语言| 函数参数传递指针
C语言| 拷贝传递(指针控制内存单元)-CSDN博客 【函数参数传指针和传数据的区别】 如果希望在另外一个函数中修改本函数中变量的值,那么在调用函数时只能传递该变量的地址。 1 普通变量,传递它的地址,可以直接操作该变量的内存空间。 举例…...

【25-cv-05917】HSP律所代理Le Petit Prince 小王子商标维权案
Le Petit Prince 小王子 案件号:25-cv-05917 立案时间:2025年5月28日 原告:SOCIETE POUR LOEUVRE ET LA MEMOIRE DANTOINE DE SAINT EXUPERY - SUCCESSION DE SAINT EXUPERY-DAGAY 代理律所:HSP 原告介绍 《小王子》&#x…...
MyBatis 动态 SQL 详解:灵活构建强大查询
MyBatis 的动态 SQL 功能是其最强大的特性之一,它允许开发者根据不同条件动态生成 SQL 语句,极大地提高了 SQL 的灵活性和复用性。本文将深入探讨 MyBatis 的动态 SQL 功能,包括 OGNL 表达式的使用以及各种动态 SQL 元素(如 if、c…...