当前位置: 首页 > news >正文

问题排查|记录一次基于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库开发的服务器错误排查(回响服务器无法正常工作)

问题背景&#xff1a; 服务器程序如下&#xff1a; #include <mymuduo/TcpServer.h> #include <mymuduo/Logger.h>#include <string> #include <functional>class EchoServer { public:EchoServer(EventLoop *loop,const InetAddress &addr, con…...

中介模式实现聊天室

中介者模式的核心逻辑就是解耦对象‘多对多’的相互依赖关系。当遇到一大堆混乱的对象呈现“网状结构”&#xff0c;利用通过中介者模式解耦对象之间的通讯。 代码案例 抽象中介类 public abstract class AbstractChatRoom {public abstract void notice(String message , Us…...

游戏开发与游戏设计区别

游戏设计与游戏开发是两个紧密相关但有着不同重点的领域&#xff0c;通常需要不同的技能和流程。以下是对游戏设计与游戏开发的详细解释&#xff0c;以及两者的区别&#xff1a; 游戏设计是关于构思和规划游戏的内容、机制和体验的过程。 主要内容: 故事和情节&#xff1a;构…...

卡尔曼滤波算法的matlab实现

卡尔曼滤波算法的matlab实现 figure; hold on;Z(1:1:100); %观测值&#xff1a;第一秒观测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 是一款基于粒子的高级物理引擎&#xff0c;可模拟各种可变形材料的行为。 使用 Obi Rope&#xff0c;你可以在几秒内创建绳索和杆子&#xff0c;同时完全控制它们的形状和行为&…...

基于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 环境下的系统编程&#xff0c;主要的用的语言是 C&#xff0c;主要是为了学习 C 语言&#xff0c;边学边写&#xff0c;这样的学习速度是比较快的。 今天就先介绍下如何在手头上没有任何资料的情况下&…...

ffmpeg 的sws_scale接口函数解析

ffmpeg 的 sws_scale 函数是 libswscale 库中的一个重要函数&#xff0c;用于进行图像的缩放和颜色空间转换。它的主要作用是将输入图像帧转换为另一种尺寸或颜色格式的输出图像帧。下面详细解析一下 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、设置官方配置文件&#xff1a;default.yaml&#xff0c;可自行修改。 3.2、设置data.yaml 4、进行训练 4.1、方法一 4.2、方法二 5、验证模型 5.1、命令行输入 5.2、脚本运行 6、总结 0、引言 本文…...

探索Web前端三大主流框架:Angular、React和Vue.js

探索Web前端三大主流框架&#xff1a;Angular、React和Vue.js 在现代Web开发中&#xff0c;前端框架已经成为开发者构建复杂应用的重要工具。Angular、React和Vue.js是目前最受欢迎的三大前端框架&#xff0c;它们各具特色&#xff0c;适用于不同的开发需求。本文将详细介绍这…...

《HelloGitHub》第 98 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 Python、…...

Xtransfer面试内容

一、Xtransfer一轮面试内容 1.进程间的通信方式 2.redis的故障转移是如何选举主节点的 3.redis快的原因 4.redis、ES、mysql选型的场景 5.redis项目的挑战和难点 6.redis和ZK各自的应用场景 7.ZK选举的算法 8.socket建立连接的过程&#xff0c;与TCP是一回事吗&#xff1f; So…...

论文笔记:Image Anaimation经典论文-运动关键点模型(Monkey-Net)

Monkey-Net&#xff08;MOviNg KEYpoints&#xff09; paper: https://arxiv.org/pdf/1812.08861, CVPR 2019 code: https://github.com/AliaksandrSiarohin/monkey-net/tree/master 相关工作 视频生成演变过程&#xff1a; spatio-temporal network: 如基于GAN网络的生成模…...

Kibana创建ElasticSearch 用户角色

文章目录 1, ES 权限参考2, 某应用的管理员权限&#xff1a;可以open/close/delete/cat/read/write 索引3, 某应用的读写权限&#xff1a;可以cat/read/write 索引 &#xff08;不能删除索引或数据&#xff09;4, 某应用的只读权限 1, ES 权限参考 https://www.elastic.co/gui…...

Vue基础(2)响应式基础

一. reactive() 在 Vue3 中&#xff0c;可以使用 reactive() 创建一个响应式对象或数组&#xff1a; <script setup> import { reactive } from vueconst state reactive({ count: 0 }) </script><template><button click"state.count">{…...

Mysql基础教程(15):别名

MySQL 别名 在本文中&#xff0c;我们讨论了 MySQL 中的列别名&#xff0c;表别名和派生表别名&#xff0c;以及使用别名来简化 SQL 和提高 SQL 的可读性。 如果在一个 SQL 中涉及到多个表&#xff0c;我们需要使用 table_name.column_name 这样的方式来引用每个表的字段&…...

SpringCloud 微服务中网关如何记录请求响应日志?

在基于SpringCloud开发的微服务中&#xff0c;我们一般会选择在网关层记录请求和响应日志&#xff0c;并将其收集到ELK中用作查询和分析。 今天我们就来看看如何实现此功能。 日志实体类 首先我们在网关中定义一个日志实体&#xff0c;用于组装日志对象 Data public class …...

【运维项目经历|028】Cobbler自动化部署平台构建项目

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 &#x1f3c5;阿里云ACE认证高级工程师 &#x1f3c5;阿里云开发者社区专…...

“物联网安全:万物互联背景下的隐私保护与数据安全策略“

在物联网&#xff08;IoT&#xff09;时代&#xff0c;随着智能设备的普及和万物互联的加速&#xff0c;隐私保护与数据安全成为了亟待解决的关键问题。以下是一些重要的隐私保护与数据安全策略&#xff0c;以确保在万物互联背景下信息的安全&#xff1a; 1. 加强设备安全&…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

小木的算法日记-多叉树的递归/层序遍历

&#x1f332; 从二叉树到森林&#xff1a;一文彻底搞懂多叉树遍历的艺术 &#x1f680; 引言 你好&#xff0c;未来的算法大神&#xff01; 在数据结构的世界里&#xff0c;“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的&#xff0c;它…...

基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)

引言 在嵌入式系统中&#xff0c;用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例&#xff0c;介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单&#xff0c;执行相应操作&#xff0c;并提供平滑的滚动动画效果。 本文设计了一个…...

CSS3相关知识点

CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...

代理服务器-LVS的3种模式与调度算法

作者介绍&#xff1a;简历上没有一个精通的运维工程师。请点击上方的蓝色《运维小路》关注我&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 我们上一章介绍了Web服务器&#xff0c;其中以Nginx为主&#xff0c;本章我们来讲解几个代理软件&#xff1a…...

Qt 按钮类控件(Push Button 与 Radio Button)(1)

文章目录 Push Button前提概要API接口给按钮添加图标给按钮添加快捷键 Radio ButtonAPI接口性别选择 Push Button&#xff08;鼠标点击不放连续移动快捷键&#xff09; Radio Button Push Button 前提概要 1. 之前文章中所提到的各种跟QWidget有关的各种属性/函数/方法&#…...