sylar高性能服务器-日志(P67-P68)内容记录

2024-03-13 03:52

本文主要是介绍sylar高性能服务器-日志(P67-P68)内容记录,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • P68-P69TcpServer封装
      • class TcpServer
        • 成员变量
        • 构造函数
        • bind(绑定地址以及监听)
        • startAccept
        • Start
        • Stop
    • echo_server

P68-P69TcpServer封装

这一节的内容对于之前学过网络编程的同学看起来比较简单一些,也没啥新的内容,都是使用之前完成的模块搭建了一个简单的echo服务器。

class TcpServer

成员变量
// 多监听,多网卡
std::vector<Socket::ptr> m_socks;
// 新连接的Socket工作的调度器, IOManager就是线程池
IOManager* m_worker;
// 服务器Socket接收连接的调度器 
IOManager* m_acceptWorker;
// 接收超时时间
uint64_t m_recvTimeout;
// 服务器名称
std::string m_name;
// 服务是否停止
bool m_isStop; 
构造函数
static sylar::ConfigVar<uint64_t>::ptr g_tcp_server_read_timeout =sylar::Config::Lookup("tcp_server.read_timeout", (uint64_t)(60 * 1000 * 2),"tcp server read timeout");TcpServer::TcpServer(sylar::IOManager* worker, sylar::IOManager* accept_worker):m_worker(worker),m_acceptWorker(accept_worker),m_recvTimeout(g_tcp_server_read_timeout->getValue()),m_name("sylar/1.0.0"),m_isStop(true) {}
bind(绑定地址以及监听)
// 绑定单个地址
bool TcpServer::bind(sylar::Address::ptr addr) {// 绑定成功的地池容器std::vector<Address::ptr> addrs;// 绑定失败的地址容器std::vector<Address::ptr> fail;addrs.push_back(addr);return bind(addrs, fail);
}// 绑定多个地址容器
bool TcpServer::bind(const std::vector<Address::ptr>& addrs, std::vector<Address::ptr>& fails) {//  m_ssl = ssl;// 遍历传入的地址容器for(auto& addr : addrs) {// Socket::ptr sock = ssl ? SSLSocket::CreateTCP(addr) : Socket::CreateTCP(addr);// 调用之前封装好的hook函数,创建一个TCP连接Socket::ptr sock = Socket::CreateTCP(addr);// 绑定失败if(!sock->bind(addr)) {SYLAR_LOG_ERROR(g_logger) << "bind fail errno="<< errno << " errstr=" << strerror(errno)<< " addr=[" << addr->toString() << "]";// 记录当前失败的地址fails.push_back(addr);// 继续下一个地址continue;}// 监听失败if(!sock->listen()) {SYLAR_LOG_ERROR(g_logger) << "listen fail errno="<< errno << " errstr=" << strerror(errno)<< " addr=[" << addr->toString() << "]";fails.push_back(addr);continue;}// 绑定、监听都成功m_socks.push_back(sock);}// 如果绑定失败的地址容器不为空,bind调用函数返回false,清空所有Socketif(!fails.empty()) {m_socks.clear();return false;}// 终端打印出绑定好的地址for(auto& i : m_socks) {// SYLAR_LOG_INFO(g_logger) << "type=" << m_type//     << " name=" << m_name//     << " ssl=" << m_sslSYLAR_LOG_INFO(g_logger)  << " server bind success: " << *i;}return true;
}
startAccept
// 服务器不断监听传入的Socket对象,等待并接收客户端的连接
void TcpServer::startAccept(Socket::ptr sock) {// 如果服务器没有停止while(!m_isStop) {// 接受一个新的客户端连接Socket::ptr client = sock->accept();// 成功接收了一个连接if(client) {// 设置服务器等待客户端发送数据的最大时间client->setRecvTimeout(m_recvTimeout);// m_ioWorker->schedule(std::bind(&TcpServer::handleClient,//             shared_from_this(), client));// 将handleClient加入到工作线程队列m_worker中m_worker->schedule(std::bind(&TcpServer::handleClient,shared_from_this(), client));} else {SYLAR_LOG_ERROR(g_logger) << "accept errno=" << errno<< " errstr=" << strerror(errno);}}
}
Start
bool TcpServer::start() {if(!m_isStop) {return true;}m_isStop = false;for(auto& sock : m_socks) {// 异步执行startAcceptm_acceptWorker->schedule(std::bind(&TcpServer::startAccept,shared_from_this(), sock));}return true;
}
Stop
void TcpServer::stop() {// 标记服务器为停止状态m_isStop = true;// 使用shared_from_this()获取当前TcpServer对象的共享指针,并将其存储在局部变量self中。// 这是为了确保在异步任务执行期间TcpServer对象不会被销毁。auto self = shared_from_this();// 这个lambda表达式捕获了this指针(即当前对象的指针)和self(即TcpServer的共享指针)。m_acceptWorker->schedule([this, self]() {for(auto& sock : m_socks) {sock->cancelAll();sock->close();}m_socks.clear();});
}

echo_server

#include "sylar/tcp_server.h"
#include "sylar/log.h"
#include "sylar/iomanager.h"
#include "sylar/bytearray.h"
#include "sylar/address.h"static sylar::Logger::ptr g_logger = SYLAR_LOG_ROOT();// EchoServer继承于TcpServer
class EchoServer : public sylar::TcpServer {
public:EchoServer(int type);// 重写void handleClient(sylar::Socket::ptr client);private:// 控制服务器行为:是否以文本或二进制形式输出接收到的数据int m_type = 0;
};EchoServer::EchoServer(int type):m_type(type) {
}// 处理客户端连接
void EchoServer::handleClient(sylar::Socket::ptr client) {// 日志打印正在处理的来自某个客户端的连接SYLAR_LOG_INFO(g_logger) << "handleClient " << *client;   // 存储从客户端接收到的数据sylar::ByteArray::ptr ba(new sylar::ByteArray);// 循环接收数据while(true) {// 清空缓冲区ba->clear();/* struct iovec{void *iov_base;	 Pointer to data.  size_t iov_len;	 Length of data.  };*/std::vector<iovec> iovs;// 用于接收客户端发送的数,这里指定了每个iovec的大小为1024字节。ba->getWriteBuffers(iovs, 1024);// 接收数据, rt保存实际接收到的字节数int rt = client->recv(&iovs[0], iovs.size());if(rt == 0) {SYLAR_LOG_INFO(g_logger) << "client close: " << *client;break;} else if(rt < 0) {SYLAR_LOG_INFO(g_logger) << "client error rt=" << rt<< " errno=" << errno << " errstr=" << strerror(errno);break;}// 移动位置指针在接收到的数据后面,不能删除,防止新接收的数据覆盖之前的数据ba->setPosition(ba->getPosition() + rt);// 设置为0方便从头读取或处理数据ba->setPosition(0);// SYLAR_LOG_INFO(g_logger) << "recv rt=" << rt << " data=" << std::string((char*)iovs[0].iov_base, rt);if(m_type == 1) {//text std::cout << ba->toString() << std::endl;// SYLAR_LOG_INFO(g_logger) << ba->toString();} else {std::cout << ba->toHexString() << std::endl;// SYLAR_LOG_INFO(g_logger) << ba->toHexString();}std::cout.flush();}
}int type = 1;void run() {SYLAR_LOG_INFO(g_logger) << "server type=" << type;EchoServer::ptr es(new EchoServer(type));// 解析传入的字符串地址 "0.0.0.0"是一个特殊的IP地址,表示服务器应该监听所有可用的网络接口。auto addr = sylar::Address::LookupAny("0.0.0.0:8020");while(!es->bind(addr)) {sleep(2);}es->start();
}int main(int argc, char** argv) {if(argc < 2) {SYLAR_LOG_INFO(g_logger) << "used as[" << argv[0] << " -t] or [" << argv[0] << " -b]";return 0;}if(!strcmp(argv[1], "-b")) {type = 2;}sylar::IOManager iom(2);iom.schedule(run);return 0;
}

服务器

image-20240312201551374

客户端

image-20240312201615264

这篇关于sylar高性能服务器-日志(P67-P68)内容记录的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/803567

相关文章

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

MySQL高性能优化规范

前言:      笔者最近上班途中突然想丰富下自己的数据库优化技能。于是在查阅了多篇文章后,总结出了这篇! 数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过32个字符 临时库表必须以tmp_为前缀并以日期为后缀,备份

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件

Linux服务器Java启动脚本

Linux服务器Java启动脚本 1、初版2、优化版本3、常用脚本仓库 本文章介绍了如何在Linux服务器上执行Java并启动jar包, 通常我们会使用nohup直接启动,但是还是需要手动停止然后再次启动, 那如何更优雅的在服务器上启动jar包呢,让我们一起探讨一下吧。 1、初版 第一个版本是常用的做法,直接使用nohup后台启动jar包, 并将日志输出到当前文件夹n

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

我在移动打工的日志

客户:给我搞一下录音 我:不会。不在服务范围。 客户:是不想吧 我:笑嘻嘻(气笑) 客户:小姑娘明明会,却欺负老人 我:笑嘻嘻 客户:那我交话费 我:手机号 客户:给我搞录音 我:不会。不懂。没搞过。 客户:那我交话费 我:手机号。这是电信的啊!!我这是中国移动!! 客户:我不管,我要充话费,充话费是你们的 我:可是这是移动!!中国移动!! 客户:我这是手机号 我:那又如何,这是移动!你是电信!!

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

记录每次更新到仓库 —— Git 学习笔记 10

记录每次更新到仓库 文章目录 文件的状态三个区域检查当前文件状态跟踪新文件取消跟踪(un-tracking)文件重新跟踪(re-tracking)文件暂存已修改文件忽略某些文件查看已暂存和未暂存的修改提交更新跳过暂存区删除文件移动文件参考资料 咱们接着很多天以前的 取得Git仓库 这篇文章继续说。 文件的状态 不管是通过哪种方法,现在我们已经有了一个仓库,并从这个仓

速盾:直播 cdn 服务器带宽?

在当今数字化时代,直播已经成为了一种非常流行的娱乐和商业活动形式。为了确保直播的流畅性和高质量,直播平台通常会使用 CDN(Content Delivery Network,内容分发网络)服务器来分发直播流。而 CDN 服务器的带宽则是影响直播质量的一个重要因素。下面我们就来探讨一下速盾视角下的直播 CDN 服务器带宽问题。 一、直播对带宽的需求 高清视频流 直播通常需要传输高清视频

学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

文章目录 删除排序链表中的重复元素我的思路解法一:循环解法二:递归 网上思路 删除排序链表中的重复元素 II我的思路网上思路 总结 删除排序链表中的重复元素 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 图一 图二 示例 1:(图一)输入:head = [1,1,2]输出:[1,2]示例 2:(图