目录
步伐计划原则
说明
Dispatcher
Callback 类
CallbackT 类
Dispatcher 类
测试
client
server
Debug
⭕参数通报错误 排查方法:
运行
纪录:
(1)Dispatcher类的功能:
- 注册消息的范例。
- 回调函数映射关系。
- 提供消息处理接口。
(2)具体实现:
- 服务端会收到不同范例的请求,客户端会收到不同范例的相应。
- 因为请求和相应都具有多样性。
- 因此 在回调函数中,就需要判定消息范例,根据不同范例的消息做出不同的处理。
- 如果单纯适用if语句做分支处理,是一件非常不好的事情。
步伐计划原则
- 步伐计划中需要依照一个原则:开闭原则 --- 对修改关闭,对扩展开放。
- 当后期维护代码或新增功能时:不去修改从前的代码,而是新增当前需要的代码。
说明
- Dispatcher模块就是基于开闭原则计划的,目的就是创建消息范例与业务回调函数的映射关系。
- 如果后期新增功能,不需要修改从前的代码,只需要增加一个映射关系即可。
Dispatcher
//调理员
- #pragma once
- #include <unordered_map>
- #include "net.hpp"
- #include "message.hpp"
- class Callback
- {
- public:
- using ptr=std::shared_ptr<Callback>;
- virtual void onMessage(const BaseConnection::ptr &conn,BaseMessage::ptr &msg)=0;
- };
- //!通过 再加 一层T,简化了 函数调用
- template<typename T>
- //要用 public 继承父类
- class CallbackT:public Callback
- {
- public:
- using ptr=std::shared_ptr<CallbackT>;
- using MessageCallback=std::function<void(const BaseConnection::ptr &conn,std::shared_ptr<T> &msg)>;
- CallbackT(const MessageCallback &handler)
- :_handler(handler)
- {}
- virtual void onMessage(const BaseConnection::ptr &conn,BaseMessage::ptr &msg) override
- {
- auto type_msg=std::dynamic_pointer_cast<T>(msg);
- _handler(conn,type_msg);
- }
- private:
- MessageCallback _handler;
- };
- class Dispatcher
- {
- public:
- using ptr=std::shared_ptr<Dispatcher>;
- template<typename T>
- //! 通过 typename 强调 传入的模板函数名
- void registerHandler(MType mtype,const typename CallbackT<T>::MessageCallback &handler)
- {
- //注册
- std::unique_lock<std::mutex> lock(_mutex);
- //!! T使得handler 更易调用了
- auto cb=std::make_shared<CallbackT<T>>(handler);
- //将 mytype和cb 解耦合 加入
- _handlers.insert(std::make_pair(mtype,cb));
- }
- void onMessage(const BaseConnection::ptr &conn,BaseMessage::ptr &msg)
- {
- std::unique_lock<std::mutex> lock(_mutex);
- auto iter=_handlers.find(msg->GetMType());
- //将 传递过来的 消息类型 进行查找
- if(iter!=_handlers.end())
- {
- return iter->second->onMessage(conn,msg);
- }
- //没有找到指定类型的处理回调--因为客户端和服务端都是我们自己设计的,因此不可能出现这种情况
- ELOG("收到 未知类型的消息:%d",msg->GetMType());
- conn->shutdown();
- }
- private:
- std::mutex _mutex;
- std::unordered_map<MType,Callback::ptr> _handlers;
- };
复制代码 0.
这段代码展示了如何使用回调(Callback)模式处理消息分发,具体来说是通过一个Dispatcher类来根据消息范例将消息分派给适当的处理器。下面是对Callback和CallbackT计划的理解:
Callback 类
- ptr: 界说了指向Callback的智能指针范例,便于管理和通报对象。
- virtual void onMessage(const BaseConnection::ptr &conn, BaseMessage::ptr &msg) = 0;: 纯虚函数,要求全部子类必须提供自己的实现。
CallbackT 类
CallbackT 是一个模板类,它继续自Callback,并为特定范例的消息提供了具体的处理逻辑。通过这种方式,它可以针对不同范例的BaseMessage提供不同的处理方式。
- onMessage 函数实现了父类中的纯虚函数,首先实验将传入的消息转换为指定范例,然后调用保存的处理函数。
Dispatcher 类
Dispatcher 负责管理不同范例消息的处理器,并根据消息范例调理到对应的处理器上。
- registerHandler 方法答应注册特定范例的消息处理器。它接收消息范例和相应的处理器(CallbackT<T>::MessageCallback),创建一个CallbackT<T>实例,并将其添加到处理器映射表中。
- onMessage 方法接收连接和消息,查找对应的消息范例处理器,并调用其onMessage方法。如果找不到符合的处理器,则纪录错误日志并关闭连接。
这种计划使得体系能够机动地处理不同种类的消息,同时保持代码的清楚和模块化。
每个消息范例都有其专门的处理器,如允许以更轻易地扩展新的消息范例及其处理逻辑。
1.typename
前文回首:6.C++模板(超全)
2.
public 忘了,报错像做梦一样
3.
就像 我们架构 当中的 一层不可,那就再套一层
测试
client
- #include "../../common/net.hpp"
- #include "../../common/message.hpp"
- #include "../../common/dispatcher.hpp"
- #include <thread>
- #include <unistd.h>
- void onRpcRespond(const BaseConnection::ptr &conn,RpcResponse::ptr &msg)
- {
- std::cout<<"收到RPC响应";
- std::string body=msg->serialize();//序列化
- std::cout<<body<<std::endl;
- }
- void onTopicRespond(const BaseConnection::ptr &conn,TopicResponse::ptr &msg)
- {
- std::cout<<"收到Topic响应";
- std::string body=msg->serialize();
- std::cout<<body<<std::endl;
- }
- int main()
- {
- auto dispatcher=std::make_shared<Dispatcher>();
- dispatcher->registerHandler<RpcResponse>(MType::RSP_RPC,onRpcRespond);
- dispatcher->registerHandler<TopicResponse>(MType::REQ_TOPIC,onTopicRespond);
- auto client=ClientFactory::create("127.0.0.1",8080);
- auto message_cb=std::bind(&Dispatcher::onMessage,dispatcher.get(),std::placeholders::_1,std::placeholders::_2);
- client->setMessageCallback(message_cb);
- client->connect();
- auto rpc_req=MessageFactory::create<RpcRequest>();
- rpc_req->setMethod("Add");
- rpc_req->SetMType(MType::REQ_RPC);
- rpc_req->SetId("1111111");
- Json::Value param;
- param["num1"]=11;
- param["num2"]=22;
- rpc_req->setParams(param);
- //调用 接口
- client->send(rpc_req);
- sleep(5);
- client->shutdown();
- return 0;
- }
复制代码 note
#include <unistd.h> 是一个在C和C++编程语言中使用的预处理指令,用于包含POSIX操作体系API的声明。这个头文件界说了各种与体系调用相关的函数、范例和宏,它们主要用于实行低级别的操作体系功能。
以下是一些由unistd.h提供的范例功能和函数:
- 历程控制:包括创建新历程(fork())、实行步伐(exec系列函数)、获取历程ID(getpid())等。
- 文件访问:虽然大多数文件操作可以通过stdio.h中的函数完成,但一些底层的操作如读写特定字节(read(), write())、更改文件当前读写位置(lseek())等需要使用unistd.h中界说的函数。
- 文件和目录操作:例如获取工作目录(getcwd())、改变工作目录(chdir())等。
- 设备I/O控制:提供了对设备进行输入输出控制的功能。
- 符号链接操作:提供创建和读取符号链接的功能。
- 用户、组和其他体系信息:答应获取和设置用户ID、组ID以及查询体系信息。
- 就寝:可以让当前历程暂停实行一段时间(sleep())。
- 多线程和同步:尽管更高级别的接口可能通过其他库提供,但是这里也可以找到一些基本的同步原语。
简朴来说,当你在编写需要直接与操作体系交互的代码时,比如 处理文件、管理历程或实行网络通信等使命时,可能会需要用到unistd.h中界说的函数。它为开发者提供了访问操作体系服务的一种方式,是Unix-like体系编程的告急组成部门
请注意,这个头文件主要是针对类Unix体系计划的,在Windows平台上并不直接适用,不过可以通过兼容层(如Cygwin)或者对应的Windows API来实现类似的功能。
server
- #include "../../common/net.hpp"
- #include "../../common/message.hpp"
- #include "../../common/dispatcher.hpp"
- #include <thread>
- void onRpcRequest(const BaseConnection::ptr &conn,RpcRequest::ptr &msg)
- {
- std::cout<<"收到RPC请求"<<msg->method();
- std::string body=msg->serialize();
- std::cout<<body<<std::endl;
- auto rpc_req=MessageFactory::create<RpcResponse>();
- rpc_req->SetId("111111");
- rpc_req->SetMType(MType::RSP_RPC);
- rpc_req->setRCode(RCode::RCODE_OK);
- rpc_req->setResult(33);
- conn->send(rpc_req);
- }
- void onTopicRequest(const BaseConnection::ptr &conn, TopicRequest::ptr &msg)
- {
- //序列化 信息检查
- std::cout << "收到Topic请求";
- std::string body = msg->serialize();
- std::cout << body << std::endl;
- //处理 回应消息
- auto rsp_req = MessageFactory::create<TopicResponse>();
- rsp_req->SetMType(MType::RSP_TOPIC);
- rsp_req->setRCode(RCode::RCODE_OK);
- rsp_req->SetId("22222");
- conn->send(rsp_req);
- }
- int main()
- {
- auto dispatcher=std::make_shared<Dispatcher>();
- dispatcher->registerHandler<RpcRequest>(MType::REQ_RPC,onRpcRequest);
- //使用 调度器 处理
- dispatcher->registerHandler<TopicRequest>(MType::REQ_TOPIC,onTopicRequest);
- auto server=ServerFactory::create(8080);
- auto message_cb=std::bind(&Dispatcher::onMessage,dispatcher.get(),std::placeholders::_1,std::placeholders::_2);
- server->setMessageCallback(message_cb);
- server->start();
- return 0;
- }
复制代码 Debug
1.
范例转化,ELOG("收到 未知范例的消息:%d",(int)msg->GetMType());
2.
⭕参数通报错误 排查方法:
查找全部引用,检查 参数顺序即可~
运行
客户端
服务端
纪录:
0.
在GDB(GNU调试器)中,bt 是 backtrace 命令的缩写。使用这个命令可以显示当前实行上下文的回溯跟踪,即步伐到达当前位置所颠末的全部函数调用列表。这对于相识步伐瓦解时的状态或者调试运行时错误非常有用。
当遇到步伐瓦解(例如段错误)、死循环或者其他非常环境时,可以通过以下步调使用 bt 命令来获取更多的信息:
- 启动GDB并加载你的步伐:你可以直接在GDB中启动你的步伐,也可以附加到一个已经运行的历程上。
- 让步伐运行:通过 run 命令启动步伐,或让它继续实行直到遇到断点或非常。
- 当步伐暂停时(如遇到瓦解或到达断点),输入 bt:这将打印出从开始到现在全部的函数调用栈帧,包括每个调用的参数值和位置信息。这对于确定问题发生的根源非常有资助。
例如,实行 bt 后你可能会看到类似下面的信息:
- #0 0x00007ffff7a6c9f0 in ?? () from /lib64/libc.so.6
- #1 0x00000000004005d8 in main () at my_program.c:10
复制代码 这里的每一行代表了调用栈中的一个层次,通常最上面的是近来被调用的函数(可能是导致瓦解的地方),而越往下则是更早之前调用的函数。通太过析这些信息,你可以更好地理解步伐实行流程,并找出潜在的问题所在。
别的,GDB还提供了其他一些与 bt 相关的命令,比如 up 和 down,用于在调用栈帧之间移动,从而检查不同层次上的局部变量和表达式值。
1.
之前忘了,反面用 n_total_len 作范围,Debug 才注意到
- h_total_len:用于当地计算和逻辑处理。在构造最终要发送的数据包时,你可能需要知道未颠末任何转换的原始长度信息来进行一些内部操作或验证。
- n_total_len:准备实际发送到网络上的数据。由于网络协议规定使用大端字节序(网络字节序)来传输数据,以是需要将主机上的数值(可能是小端字节序或其他格式)转换为网络字节序后再进行传输。
2.
数据量不足 的理解
网络查询:
在Linux和类Unix体系中,使用netstat -anptu | grep [port]命令可以查看与特定端口相关的网络连接信息。
- netstat:这是一个非常实用的网络工具,用于展示网络连接、路由表、接口统计等网络相关信息。
- -a:该选项表示显示全部连接和监听端口。它涵盖了正在监听的套接字以及处于连接状态的全部套接字等信息。
- -n:此选项指示以数字形式显示所在和端口号,不实验将它们分析为域名和服务名。这不但能加快命令实行速度,还可以制止由于域名分析可能引起的问题。
- -p:显示与网络连接关联的历程ID(PID)和历程名称。这有助于相识是哪个历程创建了相应的网络连接。
- -t:仅显示TCP协议相关的连接信息。
- -u:仅显示UDP协议相关的连接信息。
- | (管道符):用于将一个命令的输出作为另一个命令的输入。在这里,它是将netstat -anptu命令的输出通报给grep命令作为其输入。
- grep [port]:grep是一个用于搜索文件中符合模式的行的工具。在此上下文中,它被用来从netstat的输出中筛选出包含指定端口信息的行。这里的[port]应当替换为具体的端口号或端口范围等,以便正确地过滤出所需的信息。
例如,如果想要查看与80端口相关的网络连接信息,可以使用如下命令:
这条命令将会列出全部与80端口相关的TCP和UDP连接,以及对应的历程信息。通过这种方式,用户能够方便地监控和管理特定端口上的网络活动。
本日对 gitee 堆栈进行了一个整理:
Q:把Linux下写好的部门 上传到gitee
A:
最后 git push 即可
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |