首页 > 编程语言 >【C++boost::asio网络编程】有关服务端退出方法的笔记

【C++boost::asio网络编程】有关服务端退出方法的笔记

时间:2024-12-24 15:26:52浏览次数:5  
标签:asio std boost SIGINT C++ sig lock SIGTERM ioc

有关服务端退出方法的笔记


原来服务端的main函数如下

int main()
{
	try
	{
		boost::asio::io_context ioc;
		Server s(ioc, 8888);
		ioc.run();
	}
	catch (const std::exception&)
	{

	}
	return 0;
}

  上面弊端在于缺乏好的退出机制,目前,ioc.run() 会一直阻塞,直到 io_context 被显式地停止。然而,如果没有显式的退出信号或退出条件(如 SIGINT、SIGTERM 信号等),程序将无法优雅地退出。万一在运行时出现异常,或者程序需要在特定时机停止时,缺乏退出机制可能导致程序无法正常关闭。
  如果服务器程序无法响应中断信号或其他退出信号,可能会影响系统资源的释放,造成资源泄漏(如打开的网络连接、文件句柄等)。

C风格的信号关闭

#include <boost/asio.hpp>
#include <iostream>
#include "Session.h"
#include <thread>
#include <mutex>
#include <csignal>

bool bstop = false;
std::condition_variable cond_quit;
std::mutex mutex_quit;

void sig_handle(int sig)
{
	if (sig == SIGINT || sig == SIGTERM)
	{
		std::unique_lock<std::mutex> lock(mutex_quit);
		bstop = true;
		cond_quit.notify_one();
	}
}

int main()
{
	try
	{
		boost::asio::io_context ioc;
		std::thread net_work([&ioc] {
			Server s(ioc, 8888);
			ioc.run();
			});
		signal(SIGINT, sig_handle);
		signal(SIGTERM, sig_handle);
		while (!bstop)
		{
			std::unique_lock<std::mutex> lock(mutex_quit);
			cond_quit.wait(lock);
		}
		ioc.stop();
		net_work.join();
	}
	catch (const std::exception&)
	{

	}
	return 0;
}

  这里可以看到,不同于之前的主线程来进行轮询、收发数据的处理,这里采用了使用一个新线程net_work来负责原先主线程的任务,然后主线程负责监听SIGINTSIGTERM两个信号
  当程序正在运行的时候,如果想要终止程序,我们就可以通过向该进程发送信号来执行终止逻辑sig_handle。下面简单介绍一下主线程在干什么

signal(SIGINT, sig_handle);
signal(SIGTERM, sig_handle);
while (!bstop)
{
	std::unique_lock<std::mutex> lock(mutex_quit);
	cond_quit.wait(lock);
}
ioc.stop();
net_work.join();

  在while循环内部,定义了一个std::unique_lock<std::mutex>类型的变量,这个unique_lock主要就是和条件变量condition_variable 来搭配使用的。当发现当发现bstop(用来判断当前进程是否需要终止)为假时,进行循环,然后让主线程在条件变量下等待
可以不设置条件变量一直死循环吗?
  这么做虽然逻辑上可以,但是一直死循环会导致当前线程一直占用CPU资源造成资源浪费的现象,比较好的处理方案就是让该线程进入阻塞状态。然后我们给改进程发送信号时,执行sig_handle函数

void sig_handle(int sig)
{
	if (sig == SIGINT || sig == SIGTERM)
	{
		std::unique_lock<std::mutex> lock(mutex_quit);
		bstop = true;
		cond_quit.notify_one();
	}
}

  在这个函数中,会将bstop设置为true,表示整个程序应该要终止了,然后去唤醒主线程告诉它要去进行收尾的逻辑

ioc.stop();
net_work.join();

  回到主线程,退出循环之后,停止掉ioc,然后去等待回收net_work线程,回收之后再退出,此时整个程序也就安全退出了

boost::asio中的关闭方式

int main()
{
	try
	{
		boost::asio::io_context ioc;
		boost::asio::signal_set signals(ioc, SIGINT, SIGTERM);
		signals.async_wait([&ioc](auto, auto) {
			ioc.stop();
			});
		Server s(ioc, 8888);
		ioc.run();
	}
	catch (const std::exception&)
	{

	}
	return 0;
}
boost::asio::signal_set signals(ioc, SIGINT, SIGTERM);

  这一行创建了一个 boost::asio::signal_set 对象signals。signal_set 用于注册对特定信号(如中断信号 SIGINT 或终止信号 SIGTERM)的异步处理。这里注册了 SIGINT(通常是按下 Ctrl+C 时触发)和 SIGTERM(终止进程的信号)信号。
  signals 会监听这些信号,并触发相关的回调函数。

signals.async_wait([&ioc](auto, auto) { ioc.stop(); });

  这行代码使用了 async_wait 来等待信号的异步触发。回调函数会在 SIGINT 或 SIGTERM 信号到达时被调用。在回调函数内部,调用了 ioc.stop(),这会停止 io_context 的事件循环。当信号到达时,ioc.stop() 会中断事件循环的运行,允许程序优雅地退出

标签:asio,std,boost,SIGINT,C++,sig,lock,SIGTERM,ioc
From: https://blog.csdn.net/m0_74826803/article/details/144692319

相关文章

  • 实验六c++
    实验任务四源代码Vector.hpp1#include<iostream>2#include<stdexcept>3usingnamespacestd;45template<typenameT>6classVector{7public:8Vector(intn);9Vector(intn,Ta);10Vector(constVector<T>&......
  • 模拟法练习C++ 2
    1. 陶陶摘苹果题目描述陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果。苹果成熟的时候,陶陶就会跑去摘苹果。陶陶有个30厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试。现在已知10个苹果到地面的高度,以及陶陶把手伸直的时候能够达到的最大高......
  • 模拟法练习C++ 1
    有错请指出!对于模拟法,百度定义是其实,没有这么麻烦,也就是题目是什么,我们就怎么写,也可以说它是不是算法的算法,最好把代码模块化特点:1.题目简单,代码量很大2.不好找错误3.在比赛中经常考 4.代码灵活下面是几道例题1.扑克游戏题目描述三张扑克牌比大小,每个人从扑克牌中......
  • C++函数重载
    #include<stdio.h>classTimer{public:Timer(){min=0;sec=0;}voidadd(intsec){this->sec+=sec;}voidshow(){printf(&qu......
  • 真题-2021年南海区C++组真题
    这套题包含了历年真题,十分重要!!!!要考试的同学可以参考一下!!此套题限时3小时。#A.NH.2021.01.笨鸟先飞题目描述多多是一只小菜鸟,都说笨鸟先飞,多多也想来个菜鸟先飞。于是它从0点出发,一开始的飞行速度为1米/秒,每过一秒多多的飞行速度比上一秒的飞行速度快2米/秒,问n秒......
  • (2024最新毕设合集)基于SpringBoot的小说在线阅读网咖+86615|可做计算机毕业设计JAVA、P
    目 录摘要1绪论1.1 选题背景1.2研究内容1.3本文的组织结构2相关技术介绍2.1MySQL数据库2.2Java编程语言2.3SpringBoot框架介绍3 系统需求分析与设计3.1可行性分析3.1.1技术可行性分析3.1.2经济可行性分析3.1.3法律可行性分析3.2需......
  • C++ 的IO流
    C语言的输入与输出        C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()。scanf():从标准输入设备(键盘)读取数据,并将值存放在变量中。printf():将指定的文字/字符串输出到标准输出设备(屏幕)。注意宽度输出......
  • More Effective C++之技术Techniques,Idioms,Patterns_条款25
    MoreEffectiveC++之技术Techniques,Idioms,Patterns条款25:将constructor和non-memberfunction虚化constructor虚化将Non-MemberFunctions的行为虚化    本章描述C++程序员常常遭遇的一些问题的解决办法,这些解法都已获得证明。本书把这样的解法称为techniques......
  • C++ 面向对象编程:+号运算符重载,左移运算符重载
    像+、-号进行运算符重载,过程类似,见以下代码示例:#include<iostream>#include<string>usingnamespacestd;classnumber1{   friendnumber1operator+(number1&one,number1&two);public:   number1():msg1(0),msg2(1){}   number1(intmsg1,intmsg......
  • 12.23日总结之C++学习笔记-1
    *iter++是一个符合表达式,可分解为*iter和++iter,自增++的优先级要比解引用*的优先级要高,但是后缀自增表示先返回原本的值,再进行自增。也就是说上面的语句和*-i(ter++)是完全一样的。Ai解释“这是一个后缀递增操作符。它会返回当前的iter值,然后将iter增加一个位置。例如,如果......