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

『Linux_网络』 基于状态机的Connect断线重连

        客户端会面临服务器崩溃的情况, 我们可以试着写一个客户端重连的代码, 模拟并理
解一些客户端行为, 比如游戏客户端等。

        客户端部分,我们本次采用状态机的设计模式实现

下面是关于状态机模式的介绍

状态机模式

状态机模式(State Pattern)是一种行为设计模式,它能让对象在内部状态发生改变时,改变自身的行为,给人一种对象仿佛改变了类的感觉。下面从多个方面对其进行详细介绍。

模式动机

在软件开发里,某些对象的行为会依据其状态的不同而改变。若用大量的条件语句(如 if-else 或 switch-case)来处理这些状态和行为,代码会变得复杂、难以维护和扩展。状态机模式把状态的行为封装在不同的状态类中,将状态转换逻辑和对象的其他行为分离,让代码结构更清晰,提升了可维护性和可扩展性。

模式结构

状态机模式主要包含以下几个角色:

  1. 上下文(Context):拥有一个状态对象的引用,负责与客户端交互,依据不同的情况调用状态对象的方法,并且能够在状态之间进行转换。
  2. 抽象状态(State):定义了一个接口,该接口包含了所有可能的状态行为,所有具体状态类都要实现这个接口。
  3. 具体状态(Concrete State):实现了抽象状态接口,具体实现了在该状态下的行为,并且在必要时可以改变上下文的状态。

优点

  • 可维护性:状态的行为被封装在不同的类中,使得代码的维护和扩展更加容易。
  • 可扩展性:如果需要添加新的状态,只需要创建一个新的具体状态类并实现相应的行为即可。
  • 状态转换清晰:状态转换逻辑集中在上下文类中,使得状态转换更加清晰和易于管理。

缺点

  • 类数量增加:如果状态较多,会导致类的数量增加,增加了系统的复杂度。
  • 状态转换逻辑复杂:如果状态转换逻辑复杂,上下文类中的状态转换代码可能会变得复杂。

文档编辑器样例

下面给一个给一个文件编辑器的样例,来帮助理解

假设你正在开发一个文档编辑器,文档有三种状态:草稿(Draft)、审核中(Review)和已发布(Published)。文档在不同的状态下有不同的行为,比如草稿状态可以编辑和提交审核,审核中状态可以通过审核或者打回草稿,已发布状态可以查看但不能编辑。

#include <iostream>// 前向声明
class Document;// 抽象状态类
class DocumentState {
public:virtual void edit(Document* document) {}virtual void submit(Document* document) {}virtual void approve(Document* document) {}virtual void reject(Document* document) {}virtual void view(Document* document) {}virtual ~DocumentState() {}
};// 具体状态:草稿
class DraftState : public DocumentState {
public:void edit(Document* document) override {std::cout << "文档处于草稿状态,可以编辑。" << std::endl;}void submit(Document* document) override;
};// 具体状态:审核中
class ReviewState : public DocumentState {
public:void approve(Document* document) override;void reject(Document* document) override;
};// 具体状态:已发布
class PublishedState : public DocumentState {
public:void view(Document* document) override {std::cout << "文档已发布,可以查看。" << std::endl;}
};// 上下文:文档
class Document {
private:DocumentState* state;
public:Document();~Document();void setState(DocumentState* newState);void edit();void submit();void approve();void reject();void view();
};// DraftState 类的 submit 方法实现
void DraftState::submit(Document* document) {std::cout << "文档已提交审核。" << std::endl;document->setState(new ReviewState());
}// ReviewState 类的 approve 方法实现
void ReviewState::approve(Document* document) {std::cout << "文档审核通过,已发布。" << std::endl;document->setState(new PublishedState());
}// ReviewState 类的 reject 方法实现
void ReviewState::reject(Document* document) {std::cout << "文档审核未通过,打回草稿。" << std::endl;document->setState(new DraftState());
}// Document 类的构造函数
Document::Document() {state = new DraftState();
}// Document 类的析构函数
Document::~Document() {delete state;
}// Document 类的 setState 方法
void Document::setState(DocumentState* newState) {delete state;state = newState;
}// Document 类的 edit 方法
void Document::edit() {state->edit(this);
}// Document 类的 submit 方法
void Document::submit() {state->submit(this);
}// Document 类的 approve 方法
void Document::approve() {state->approve(this);
}// Document 类的 reject 方法
void Document::reject() {state->reject(this);
}// Document 类的 view 方法
void Document::view() {state->view(this);
}int main() {Document document;document.edit();document.submit();document.approve();document.view();return 0;
}    

Connect 断线重连具体实现

Connect.hpp

 

 Client.cc

 测试Debug

测试部分,我采用我们在Linux网络篇Tcp章节所编写的翻译服务器测试以及将实现客户端与服务器通信的代码放入process中

 编译运行,服务器和客户端之间就可以进行通信了

断掉服务器,再启动服务器,重新连接的服务也是支持的 

但是我们发现每次与服务器通信,都会有一个connect success... 的提示语,那么我们怎么去掉它呢?

 首先,我们需要明确为什么每次通信都会打印这个信息

这是因为,我们服务器与客户端之间的通信循环走的是外面的这个状态判断,当状态为CONNECTED的时候,我们正常执行process代码,但当第二次循环的时候,由于我们连接状态一直是成功的,所以再执行这里的时候,还是会打印这条信息,那我们应该怎么办呢?

有两种方法,第一种在设计一种状态,就是当连接建立成功的时候,就只执行process,而不去打印这条提示语。

还记得我们之间设计的Connceting状态吗,当时说的可有可无,在这里我们就可以利用这个状态,而不用去在取名一个新的状态了。

像这样

每次进入process,就设置状态正在连接中。

在状态循环中添加这样的一条判断

编译运行,发现就没有这样的提示了

 

同样也是支持断线重连的 

 

但是这个方法也体现了状态机的一个缺点,就是状态数量的增加,状态之间的复杂性问题。

第二种方法,就是将外面的循环挪到process中,这样就不需要借助于状态判断的循环来维持服务器与客户端之间的通信了 。

实现很简单,就是在Process内部加一个循环循环条件是当前状态为connected,修改状态的时候,就可以自动退出了

 

编译运行,各种功能也是支持的

 


 至此,我们的基于状态机实现Client断线重连,就结束了。

如有什么问题,欢迎评论区留言提问。

相关文章:

  • 哈希表的设计
  • 基于STM32、HAL库的NS2009 触摸屏控制器驱动程序设计
  • 第二节:Vben Admin 最新 v5.0 对接后端登录接口(上)
  • LintCode第484题-交换数组两个元素,第9题-Fizz Buzz 问题,第46题-主元素,第50题数组剔除元素后的乘积
  • GAN模型
  • 芝法酱躺平攻略(22)——rabbitmq安装和使用(二)
  • WiFi那些事儿(六)
  • 链表的面试题2反转单链表
  • 从0开始学习大模型--Day2--大模型的工作流程以及初始Agent
  • 码蹄集——直角坐标到极坐标的转换、射线、线段
  • 2018年ASOC SCI1区TOP,混合灰狼算法HBBOG,深度解析+性能实测
  • 机器视觉框架源码——解读3(常用的资源和样式)
  • 在c++中老是碰到string,这是什么意思?
  • 大模型系列(三)--- GPT1论文研读
  • 若依微服务框架在docker-compose中部署
  • IDEA 安装 SpotBugs 插件超简单教程
  • 【AI提示词】类比思维专家
  • 产品经理如何借助 DeepSeek 提升工作效能
  • 可炫可转防丢帽 金士顿DTXS闪存盘致敬经典
  • Git 使用的全流程以及SourceTree工具的使用操作和忽略文件的配置
  • 商务部新闻发言人就中美经贸高层会谈答记者问
  • 夜读丨最美的风景,在亲人的目光里
  • 起底新型保健品电话销售诈骗:从快递信息中筛选对象,忽悠其高价买药
  • 中年人多活动有助预防阿尔茨海默病
  • 习近平将对俄罗斯进行国事访问并出席纪念苏联伟大卫国战争胜利80周年庆典
  • 成为中国骑手孵化器,上海环球马术冠军赛是最好的历练舞台