问题排查|记录一次基于mymuduo库开发的服务器错误排查(回响服务器无法正常工作)
问题背景:
服务器程序如下:
#include <mymuduo/TcpServer.h>
#include <mymuduo/Logger.h>#include <string>
#include <functional>class EchoServer
{
public:EchoServer(EventLoop *loop,const InetAddress &addr, const std::string &name): server_(loop, addr, name), loop_(loop){// 注册回调函数server_.setConnectionCallback(std::bind(&EchoServer::onConnection, this, std::placeholders::_1));server_.setMessageCallback(std::bind(&EchoServer::onMessage, this,std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));// 设置合适的loop线程数量 loopthreadserver_.setThreadNum(2);}void start(){server_.start();}
private:// 连接建立或者断开的回调void onConnection(const TcpConnectionPtr &conn){if (conn->connected()){LOG_INFO("Connection UP : %s", conn->peerAddress().toIpPort().c_str());}else{LOG_INFO("Connection DOWN : %s", conn->peerAddress().toIpPort().c_str());}}// 可读写事件回调void onMessage(const TcpConnectionPtr &conn,Buffer *buf,Timestamp time){std::string msg = buf->retrieveAllAsString();conn->send(msg);conn->shutdown(); // 写端 EPOLLHUP =》 closeCallback_}EventLoop *loop_;TcpServer server_;
};int main()
{EventLoop loop;InetAddress addr(8000);EchoServer server(&loop, addr, "EchoServer-01"); // Acceptor non-blocking listenfd create bind server.start(); // listen loopthread listenfd => acceptChannel => mainLoop =>loop.loop(); // 启动mainLoop的底层Pollerreturn 0;
}
另起一个终端,其中使用命令:
sudo telnet 127.0.0.1 8000
会导致服务器端有以下错误:
[INFO]2024/05/31 21:51:16: channel handleEvent revents: 1
[INFO]2024/05/31 21:51:16: 1 events happened [INFO]2024/05/31 21:51:16: channel handleEvent revents: 1
[INFO]2024/05/31 21:51:16: 1 events happened [INFO]2024/05/31 21:51:16: channel handleEvent revents: 1
[INFO]2024/05/31 21:51:16: 1 events happened [INFO]2024/05/31 21:51:16: channel handleEvent revents: 1
[INFO]2024/05/31 21:51:16: 1 events happened [INFO]2024/05/31 21:51:16: channel handleEvent revents: 1
[INFO]2024/05/31 21:51:16: 1 events happened [INFO]2024/05/31 21:51:16: channel handleEvent revents: 1
[INFO]2024/05/31 21:51:16: 1 events happened [INFO]2024/05/31 21:51:16: channel handleEvent revents: 1
[INFO]2024/05/31 21:51:16: 1 events happened [INFO]2024/05/31 21:51:16: channel handleEvent revents: 1
[INFO]2024/05/31 21:51:16: 1 events happened [INFO]2024/05/31 21:51:16: channel handleEvent revents: 1
[INFO]2024/05/31 21:51:16: 1 events happened
服务器一直循环打印如下内容
问题分析
epoll_wait 一直返回并触发 EPOLLIN 事件,这通常是因为某个文件描述符一直处于可读状态,但没有正确处理。这种情况最常见的原因是未正确读取客户端发送的数据,导致 epoll 一直认为有数据可读,从而不断触发可读事件。
分析和调试步骤
首先使用gdb调试,然后把整个服务跑起来,随后起另一个终端:
sudo telnet 127.0.0.1 8000
连接之后复现出问题,
随后在gdb中中断程序,成功捕捉到出问题的地方,这里大概就是在EventLoop::loop(),然后在EpollPoller::poll()处,
现在我们可以分析问题了,本来应该在新连接建立后,就由TcpConnection来进行连接的管理了,现在在循环打印poll中的内容,说明epoll_wait根本就没有呗阻塞。
再一个,就算我们把telnet连接断开,服务器仍然会不断打印EpollPoller::poll()的内容,那么抓到问题了,肯定是channel的原因。
那么我们就开始差channel吧,首先需要关注的是文件描述符是否正常,设置的感兴趣的事件是否正常,最后就是被激活的事件是否正常。
打印之后发现确实没啥毛病。
这么说的话,我们需要重新审视该问题,如果一个channel不停得在循环打印EpollPoller::poll()得内容,并且channel中封装的文件描述符也都正常,那最主要的问题就在于channel相关的回调函数没有被正确设置,或者逻辑有重大问题。
后来顺着channel执行回调的地方顺逻辑,也没发现什么问题;
然后我突然想到新连接建立的时候,那个channel是由Acceptor打包的,它的主要任务不就是监听新用户连接,打包成channel,然后把它们分发给subloop吗?
直接先看Acceptor的构造函数:
acceptChannel_.setErrorCallback(std::bind(&Acceptor::handleRead, this));
在构造函数中我竟然没有设置读回调,直接大错特错,而且Acceptor::handleRead本来就是它的读回调啊!!!
把它改成:
acceptChannel_.setReadCallback(std::bind(&Acceptor::handleRead, this));
至此,问题解决。
相关文章:
问题排查|记录一次基于mymuduo库开发的服务器错误排查(回响服务器无法正常工作)
问题背景: 服务器程序如下: #include <mymuduo/TcpServer.h> #include <mymuduo/Logger.h>#include <string> #include <functional>class EchoServer { public:EchoServer(EventLoop *loop,const InetAddress &addr, con…...
中介模式实现聊天室
中介者模式的核心逻辑就是解耦对象‘多对多’的相互依赖关系。当遇到一大堆混乱的对象呈现“网状结构”,利用通过中介者模式解耦对象之间的通讯。 代码案例 抽象中介类 public abstract class AbstractChatRoom {public abstract void notice(String message , Us…...
游戏开发与游戏设计区别
游戏设计与游戏开发是两个紧密相关但有着不同重点的领域,通常需要不同的技能和流程。以下是对游戏设计与游戏开发的详细解释,以及两者的区别: 游戏设计是关于构思和规划游戏的内容、机制和体验的过程。 主要内容: 故事和情节:构…...
卡尔曼滤波算法的matlab实现
卡尔曼滤波算法的matlab实现 figure; hold on;Z(1:1:100); %观测值:第一秒观测1m 第二秒观测两米 匀速运动, 每秒1m, 最后拟合的也是速度 1m/splot(Z); plot([0,100], [1,1]);noiserandn(1,100)*0.5; %生成方差为1的高斯噪声 ZZnoise; % 加入噪声plot(Z);X[0;…...
Unity Obi Rope失效
文章目录 前言一、WebGL端Obi Rope失效二、Obi Rope 固定不牢三、使用Obi后卡顿总结 前言 Obi 是一款基于粒子的高级物理引擎,可模拟各种可变形材料的行为。 使用 Obi Rope,你可以在几秒内创建绳索和杆子,同时完全控制它们的形状和行为&…...
基于Nginx和Consul构建自动发现的Docker服务架构——非常之详细
基于Nginx和Consul构建自动发现的Docker服务架构 文章目录 基于Nginx和Consul构建自动发现的Docker服务架构资源列表基础环境一、安装Docker1.1、Consul节点安装1.2、registrator节点安装 二、案例前知识点2.1、什么是Consul 三、基于Nginx和Consul构建自动发现的Docker服务架构…...
Gnu/Linux 系统编程 - 如何获取帮助及一个演示
Gnu/Linux 系统编程 - 如何获取帮助及一个演示 今天开始写 Gnu/Linux 环境下的系统编程,主要的用的语言是 C,主要是为了学习 C 语言,边学边写,这样的学习速度是比较快的。 今天就先介绍下如何在手头上没有任何资料的情况下&…...
ffmpeg 的sws_scale接口函数解析
ffmpeg 的 sws_scale 函数是 libswscale 库中的一个重要函数,用于进行图像的缩放和颜色空间转换。它的主要作用是将输入图像帧转换为另一种尺寸或颜色格式的输出图像帧。下面详细解析一下 sws_scale 函数的作用、参数等。 sws_scale 函数的作用 ffmpeg 的 sws_sca…...
MoonBit 本周新增类型标注语法、继续进行核心库 API 整理工作
MoonBit更新 类型标注增加了新的语法T? 来表示Option[T] struct Cell[T] {val: Tnext: Cell[T]? }fn f(x : Cell[T]?) -> Unit { ... }相当于 struct Cell[T] {val: Tnext: Option[Cell[T]] }fn f(x : Option[Cell[T]]) -> Unit { ... }旧的Option[T]仍然兼容&…...
YOLOv10训练自己的数据集
目录 0、引言 1、环境配置 2、数据集准备 3、创建配置文件 3.1、设置官方配置文件:default.yaml,可自行修改。 3.2、设置data.yaml 4、进行训练 4.1、方法一 4.2、方法二 5、验证模型 5.1、命令行输入 5.2、脚本运行 6、总结 0、引言 本文…...
探索Web前端三大主流框架:Angular、React和Vue.js
探索Web前端三大主流框架:Angular、React和Vue.js 在现代Web开发中,前端框架已经成为开发者构建复杂应用的重要工具。Angular、React和Vue.js是目前最受欢迎的三大前端框架,它们各具特色,适用于不同的开发需求。本文将详细介绍这…...
《HelloGitHub》第 98 期
兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等,涵盖多种编程语言 Python、…...
Xtransfer面试内容
一、Xtransfer一轮面试内容 1.进程间的通信方式 2.redis的故障转移是如何选举主节点的 3.redis快的原因 4.redis、ES、mysql选型的场景 5.redis项目的挑战和难点 6.redis和ZK各自的应用场景 7.ZK选举的算法 8.socket建立连接的过程,与TCP是一回事吗? So…...
论文笔记:Image Anaimation经典论文-运动关键点模型(Monkey-Net)
Monkey-Net(MOviNg KEYpoints) paper: https://arxiv.org/pdf/1812.08861, CVPR 2019 code: https://github.com/AliaksandrSiarohin/monkey-net/tree/master 相关工作 视频生成演变过程: spatio-temporal network: 如基于GAN网络的生成模…...
Kibana创建ElasticSearch 用户角色
文章目录 1, ES 权限参考2, 某应用的管理员权限:可以open/close/delete/cat/read/write 索引3, 某应用的读写权限:可以cat/read/write 索引 (不能删除索引或数据)4, 某应用的只读权限 1, ES 权限参考 https://www.elastic.co/gui…...
Vue基础(2)响应式基础
一. reactive() 在 Vue3 中,可以使用 reactive() 创建一个响应式对象或数组: <script setup> import { reactive } from vueconst state reactive({ count: 0 }) </script><template><button click"state.count">{…...
Mysql基础教程(15):别名
MySQL 别名 在本文中,我们讨论了 MySQL 中的列别名,表别名和派生表别名,以及使用别名来简化 SQL 和提高 SQL 的可读性。 如果在一个 SQL 中涉及到多个表,我们需要使用 table_name.column_name 这样的方式来引用每个表的字段&…...
SpringCloud 微服务中网关如何记录请求响应日志?
在基于SpringCloud开发的微服务中,我们一般会选择在网关层记录请求和响应日志,并将其收集到ELK中用作查询和分析。 今天我们就来看看如何实现此功能。 日志实体类 首先我们在网关中定义一个日志实体,用于组装日志对象 Data public class …...
【运维项目经历|028】Cobbler自动化部署平台构建项目
🍁博主简介: 🏅云计算领域优质创作者 🏅2022年CSDN新星计划python赛道第一名 🏅2022年CSDN原力计划优质作者 🏅阿里云ACE认证高级工程师 🏅阿里云开发者社区专…...
“物联网安全:万物互联背景下的隐私保护与数据安全策略“
在物联网(IoT)时代,随着智能设备的普及和万物互联的加速,隐私保护与数据安全成为了亟待解决的关键问题。以下是一些重要的隐私保护与数据安全策略,以确保在万物互联背景下信息的安全: 1. 加强设备安全&…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
P3 QT项目----记事本(3.8)
3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...
【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
