网络编程之LINUX信号

news2024/9/20 8:57:54

注意发送信号是给进程,不是线程,调用的是KILL函数,SIG是信号种类。pid=0是本进程的其他的进程。

 可以通过设置ERRNO来查看返回的错误,如下:

当目标进程收到信号后,要对信号进行一些执行操作:

定义的接受函数一般作为函数指针,交给系统调用sigaction进行执行函数的调用。

在LINUX中,信号有多种,一般只需要关注网络相关如下几个信号

1.通知系统状态变化:比如alarm定时器或者setitimer定时发送的信号 SIGALRM

2.SIGHUP:控制终端进行挂起

3.SIGPIPE:往读端被关闭的通道或者SOCKET连接中写入数据

4.SIGURG:SOCKET上接收到紧急数据。

代码如下:

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>

#define BUF_SIZE 1024

static int connfd;

void sig_urg( int sig )
{
    int save_errno = errno;
    
    char buffer[ BUF_SIZE ];
    memset( buffer, '\0', BUF_SIZE );
    int ret = recv( connfd, buffer, BUF_SIZE-1, MSG_OOB );//接受带外数据
    printf( "got %d bytes of oob data '%s'\n", ret, buffer );

    errno = save_errno;
}

void addsig( int sig, void ( *sig_handler )( int ) )
{
    struct sigaction sa;
    memset( &sa, '\0', sizeof( sa ) );
    sa.sa_handler = sig_handler;
    sa.sa_flags |= SA_RESTART;
    sigfillset( &sa.sa_mask );
    assert( sigaction( sig, &sa, NULL ) != -1 );
}

int main( int argc, char* argv[] )
{
    if( argc <= 2 )
    {
        printf( "usage: %s ip_address port_number\n", basename( argv[0] ) );
        return 1;
    }
    const char* ip = argv[1];
    int port = atoi( argv[2] );

    struct sockaddr_in address;
    bzero( &address, sizeof( address ) );
    address.sin_family = AF_INET;
    inet_pton( AF_INET, ip, &address.sin_addr );
    address.sin_port = htons( port );

    int sock = socket( PF_INET, SOCK_STREAM, 0 );
    assert( sock >= 0 );

    int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
    assert( ret != -1 );

    ret = listen( sock, 5 );
    assert( ret != -1 );

    struct sockaddr_in client;
    socklen_t client_addrlength = sizeof( client );
    connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
    if ( connfd < 0 )
    {
        printf( "errno is: %d\n", errno );
    }
    else
    {
        addsig( SIGURG, sig_urg );//发起引号
        fcntl( connfd, F_SETOWN, getpid() );//使用SIGURG时,必须设置SOCKET的主进程或进程组

        char buffer[ BUF_SIZE ];
        while( 1 )
        {
            memset( buffer, '\0', BUF_SIZE );
            ret = recv( connfd, buffer, BUF_SIZE-1, 0 );
            if( ret <= 0 )
            {
                break;
            }
            printf( "got %d bytes of normal data '%s'\n", ret, buffer );
        }

        close( connfd );
    }

    close( sock );
    return 0;
}
/*带外信号就是紧急信息,比如TCP紧急指针,紧急信息有着更高级的发送优先权,所以会排在普通信息的最前面,第一个被发送出去。*/

上述情况要注意,阻塞I/O在阻塞时即使收到信号也不会调用信号处理,而是会被中断系统调用,比如read(),write()等阻塞I/O。

对于是暂停信号的接受,没有设置信号的处理函数,则会中断epoll_wait,connect等调用。

        下面介绍信号函数:

1.

signal系统调用一般并不常用,而是使用sigaction函数。

2.

注意二三参数都是sigaction类结构体指针,该结构体类型如下:

成员变量sa_handler是信号处理相关的函数指针。

sa_mask是成员设置进程的信号掩码,用于内核进行运算执行,其是信号集sigset_t类型。信号集就是一个数组,类似于fd_set,该数组的每一位都表示一个信号。对于网络编程,一般不需要设置特殊的sa_mask.用函数sigfillset进行初始化即可。

sa_flags是标志量,用于告诉程序收到信号时的行为,应该做什么。

代码如下:

#include <sys/socket.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <sys/epoll.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <iostream>
#include <fcntl.h>

const int MAX_EVENT_SIZE=1024;
static int pipefd[2];

int setnoblocking(int fd){
    int res=fcntl(fd,F_GETFL);
    int new_opation=res|O_NONBLOCK;
    fcntl(fd,F_SETFL,new_opation);
    return fd;
}

void addfd(int epollfd,int fd){
     epoll_event event;
     event.data.fd=fd;
     event.events=EPOLLET|EPOLLIN;
     epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,event);
     setnoblocking(fd);
}

void sig_handler(int sig){
    int save_errno=errno;
    int mig=sig;
    send(pipefd[1],(char*)&mig,1,0);
    errno=save_errno;
}

void addsig(int sig){
    struct sigaction tem;
    tem.sa_handler=sig_handler;
    tem.sa_flags|=SA_RESTART;
    sigfillset(&tem.sa_mask);
   int ret=sigaction(sig,&tem,NULL);
   assert(ret>=0);
}


  int main(int argc,char* argv[]){
      if(argc<=2){
        std::cout<<"error"<<std::endl;
        exit(1);
      }

      const char* ip=argv[1];
      int port=atoi(argv[2]);

      int ret=0;
      struct sockaddr_in address;
      memest(&address,0,sizeof(address));
      address.sin_family=AF_INET;
      inet_pton(AF_INET,ip,&address.sin_addr);
      address.sin_port=htonl(port);

      int listenfd=socket(PF_INET,SOCK_STREAM,0);
      if(bind(listenfd,(struct sockaddr*)&address,sizeof(address))==-1){
        std::cout<<"bind() error"<<std::endl;
        exit(1);
      }

      if(listen(listenfd,5)==-1){
        std::cout<<"listen() error"<<std::endl;
        exit(1);
      }

     epoll_event events[MAX_EVENT_SIZE];
      int epollfd=epoll_create(5);
      addfd(epollfd,listenfd);
      
      ret=socketpair(PF_UNIX,SOCK_STREAM,0,pipefd);
       setnoblocking(pipefd[1]);//只将写入端加入到非阻塞,而不是监听
       addfd(epollfd,pipefd[0]);//注册可读事件

       addsig(SIGHUP);
       addsig(SIGCHLD);
       addsig(SIGTERM);
       addsig(SIGINT);

       bool stop_server=false;


      while(!stop_server){
int res=epoll_wait(epollfd,events,MAX_EVENT_SIZE,-1);
    if((res<0)&&(errno!=EINTR)){//EINTR 系统调用被中断
        std::cout<<"epoll error"<<std::endl;
        break;
    }
   for(int i=0;i<res;i++){
    int sockfd=events[i].data.fd;
    if(sockfd==listenfd){
        struct sockaddr_in client_data;
        socklen_t size=sizeof(client_data);
        int p=accept(listenfd,(struct sockaddr* &client_data,&size));
        addfd(epollfd,p);
    }else if(sockfd==pipefd[0]&&(events[i].events&EPOLLIN)){
        int sig;
        char siganls[1024];
        ret=recv(pipefd[0],siganls,sizeof(siganls),0);
        if(ret==-1){
            continue;
        }else if(ret==0){
            continue;
        }else{
            for(int i=0;i<ret;i++){
                switch (siganls[i])
                {
                case SIGCHLD:
                 case SIGHUP:{
                  continue;//
                }
                case SIGTERM:
                case SIGINT:
                {
                 stop_server=true;
                }
                
                }
            }
        }
    }
   else{

   }

      }
      }      
std::cout<<"close fd"<<std::endl;
close(listenfd);
close(pipefd[1]);
close(pipefd[0]);
return 0;


  }

总结就是设置信号处理函数时,处理函数将收到信号通过管道方式传递给主循环进行聆听判断,对不同信号做出相应的反应。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1940713.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[每周一更]-(第106期):DNS和SSL协作模式

文章目录 什么是DNS&#xff1f;DNS解析过程DNS解析的底层逻辑 什么是SSL&#xff1f;SSL证书SSL握手过程SSL的底层逻辑 DNS与SSL的协同工作过程 什么是DNS&#xff1f; DNS&#xff08;Domain Name System&#xff0c;域名系统&#xff09;是互联网的重要组成部分&#xff0c…

黑马程序员MySQL基础学习,精细点复习【持续更新】

文章目录 数据库Mysql基础一、数据库1.数据库2.数据库管理系统3.SQL4.Mysql目录结构5.关系型数据库6.SQL基础概念 mysql高级一、数据库备份和还原1.图形化界面备份与还原 二、约束1.分类&#xff1a;2.主键约束3.唯一约束4.非空约束5.默认值约束6.外键约束 三、表关系1.概述2.一…

《Windows API每日一练》13.1 打印基础

在Windows中使用打印机时&#xff0c;在调用一系列与打印相关的GDI绘图函数的背后&#xff0c;实际上启动了一系列模块之间复杂的交互过程&#xff0c;包括 GDI32库模块、打印机设备驱动程序库模块&#xff08;带.DRV后缀的文件&#xff09;、Windows后台打印处理程序&#xff…

5. harbor镜像仓库

harbor镜像仓库 一、镜像仓库1、类型2、构建私有仓库的方案 二、部署harbor仓库(单机版)1、安装docker(略)2、安装docker-compose工具3、安装harbor4、生成harbor需要的证书、密钥(V3版本证书)4.1 创建CA4.2 创建harbor仓库需要的证书 5、编辑harbor配置文件6、启动harbor 三、…

【C++】17.AVL树

一、AVL树的概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索树将退化为单支树&#xff0c;查找元素相当于在顺序表中搜索元素&#xff0c;效率低下。因此&#xff0c;两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种…

Linux实用操作二

文章目录 Linux实用操作二日期、时区&#xff1a;date命令查看日期时间作用&#xff1a;语法&#xff1a;字段解释&#xff1a;操作&#xff1a; 修改Linux系统时区作用&#xff1a;操作&#xff1a; 使用ntp进行时间同步和校准作用&#xff1a;操作&#xff1a; IP地址、主机名…

buuctf web 第五到八题

[ACTF2020 新生赛]Exec 这里属实有点没想到了&#xff0c;以为要弹shell&#xff0c;结果不用 127.0.0.1;ls /PING 127.0.0.1 (127.0.0.1): 56 data bytes bin dev etc flag home lib media mnt opt proc root run sbin srv sys tmp usr var127.0.0.1;tac /f*[GXYCTF2019]Pin…

【数学建模】多波束测线问题(持续更新)

多波束测线问题 问题 1建立模型覆盖宽度海水深度重叠长度重叠率 问题二问题三问题四 问题 1 与测线方向垂直的平面和海底坡面的交线构成一条与水平面夹角为 α \alpha α的斜线&#xff08;如下图&#xff09;&#xff0c;称 α \alpha α为坡度。请建立多波束测深的覆盖宽度及…

世界华人国学泰斗级人物颜廷利:人类史上全球公认最伟大的思想家

世界华人国学泰斗级人物颜廷利:人类史上全球公认最伟大的思想家 颜廷利教授,一位在21世纪东方哲学、科学界具有深远影响力的人物,同时也是当代中国教育界的知名教授、周易起名与易经姓名学的专家,以及现代国学的杰出代表。他在其著作《升命学说》中提出了一系列独到的理论,包括…

Mybatis--分页查询

一、分页查询 分页查询则是在页面上将本来很多的数据分段显示&#xff0c;每页显示用户自定义的行数。可提高用户体验度&#xff0c;同时减少一次性加载&#xff0c;内存溢出风险。 1、真假分页 分页分为&#xff1a;真分页和假分页。 假分页&#xff1a;一次性查询所有数据存入…

笔记小结:卷积神经网络之多输入多输出通道

本文为李沐老师《动手学深度学习》笔记小结&#xff0c;用于个人复习并记录学习历程&#xff0c;适用于初学者 彩色图像具有标准的RGB通道来代表红、绿和蓝&#xff0c;需要三个通道表示&#xff0c;故而只有单输入单输出是不够的。 对于单个输入和单个输出通道的简化例子&…

Yolo-World网络模型结构及原理分析(一)——YOLO检测器

文章目录 概要一、整体架构分析二、详细结构分析YOLO检测器1. Backbone2. Head3.各模块的过程和作用Conv卷积模块C2F模块BottleNeck模块SPPF模块Upsampling模块Concat模块 概要 尽管YOLO&#xff08;You Only Look Once&#xff09;系列的对象检测器在效率和实用性方面表现出色…

【引领未来智造新纪元:量化机器人的革命性应用】

在日新月异的科技浪潮中&#xff0c;量化机器人正以其超凡的智慧与精准的操作&#xff0c;悄然改变着各行各业的生产面貌&#xff0c;成为推动产业升级、提升竞争力的关键力量。今天&#xff0c;让我们一同探索量化机器人在不同领域的广泛应用价值&#xff0c;见证它如何以科技…

CSA笔记4-包/源管理命令以及本地光盘仓库搭建

包/源管理命令 1.rpm是最基础的rmp包的安装命令&#xff0c;需要提前下载相关安装包和依赖包 2.yum/dnf是基于rpm包的自动安装命令&#xff0c;可以自动在仓库中匹配安装软件和依赖包 注意:以上是安装命令&#xff0c;以下是安装源 3.光盘源&#xff1a;是指安装系统时后的…

Air780EP- AT开发-阿里云应用指南

简介 使用AT方式连接阿里云分为一机一密和一型一密两种方式&#xff0c;其中一机一密又包括HTTP认证二次连接和MQTT直连两种方式 关联文档和使用工具&#xff1a; AT固件获取在线加/解密工具阿里云平台 准备工作 Air780EP_全IO开发板一套&#xff0c;包括天线SIM卡&#xff0…

华为云技术精髓笔记(四)-CES基础入门实战

华为云技术精髓笔记(四) CES基础入门实战 一、监控ECS性能 1、 远程登录ECS 步骤一 双击实验桌面的“Xfce终端”打开Terminal&#xff0c;输入以下命令登录云服务器。注意&#xff1a;请使用云服务器的公网IP替换命令中的【EIP】。 LANGen_us.UTF-8 ssh rootEIP说明&#x…

中国自然灾害影响及损失数据

自然灾害往往会导致大量的人员伤亡和财产损失&#xff0c;数据集详细记载了2014-2020年中国自然灾害影响以及灾害造成的损失情况。其中包括地震、台风、雨雪、阵雨、雪灾、暴雨、旱灾、龙卷风、泥石流、山崩、泥石流、滑坡、洪涝等灾害事件。 数据集主要以excel的格式存储。属性…

【学术会议征稿】第二届人工智能与自动化控制国际学术会议(AIAC 2024)

第二届人工智能与自动化控制国际学术会议&#xff08;AIAC 2024&#xff09; The 2nd International Conference on Artificial Intelligence and Automation Control 随着技术的迅猛发展&#xff0c;人工智能与自动化控制已经深入到工业、交通、医疗、教育等各个领域&#x…

【Linux】-----权限详解

目录 一、Linux下的权限概念 Ⅰ、是什么&#xff1f; Ⅱ、Linux下的两种角色 角色 如何添加普通用户 身份的转化方式 身份的提权 添加普通用户至白名单 二、Linux下的权限管理 Ⅰ、文件访问者的分类(Linux下的“人”) Ⅱ、文件类型和访问权限(事物属性) 1.文件类型 …

为什么阿里巴巴超级喜欢java开发?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「java的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; 我猜可能是因为&#xff0…