zoukankan      html  css  js  c++  java
  • 04Linux网络编程基础 ---- 信号

    1. 统一事件源:

      1 #include <sys/types.h>
      2 #include <sys/socket.h>
      3 #include <netinet/in.h>
      4 #include <arpa/inet.h>
      5 #include <assert.h>
      6 #include <stdio.h>
      7 #include <signal.h>
      8 #include <unistd.h>
      9 #include <errno.h>
     10 #include <string.h>
     11 #include <fcntl.h>
     12 #include <stdlib.h>
     13 #include <sys/epoll.h>
     14 #include <pthread.h>
     15 
     16 #define MAX_EVENT_NUMBER 1024
     17 static int pipefd[2];
     18 
     19 int setnonblocking( int fd )
     20 {
     21     int old_option = fcntl( fd, F_GETFL );
     22     int new_option = old_option | O_NONBLOCK;
     23     fcntl( fd, F_SETFL, new_option );
     24     return old_option;
     25 }
     26 
     27 void addfd( int epollfd, int fd )
     28 {
     29     epoll_event event;
     30     event.data.fd = fd;
     31     event.events = EPOLLIN | EPOLLET;
     32     epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event );
     33     setnonblocking( fd );
     34 }
     35 
     36 void sig_handler( int sig )
     37 {
     38     int save_errno = errno;
     39     int msg = sig;
     40     send( pipefd[1], ( char* )&msg, 1, 0 );
     41     errno = save_errno;
     42 }
     43 
     44 void addsig( int sig )
     45 {
     46     struct sigaction sa;
     47     memset( &sa, '', sizeof( sa ) );
     48     sa.sa_handler = sig_handler;
     49     sa.sa_flags |= SA_RESTART;
     50     sigfillset( &sa.sa_mask );
     51     assert( sigaction( sig, &sa, NULL ) != -1 );
     52 }
     53 
     54 int main( int argc, char* argv[] )
     55 {
     56     if( argc <= 2 )
     57     {
     58         printf( "usage: %s ip_address port_number
    ", basename( argv[0] ) );
     59         return 1;
     60     }
     61     const char* ip = argv[1];
     62     int port = atoi( argv[2] );
     63 
     64     int ret = 0;
     65     struct sockaddr_in address;
     66     bzero( &address, sizeof( address ) );
     67     address.sin_family = AF_INET;
     68     inet_pton( AF_INET, ip, &address.sin_addr );
     69     address.sin_port = htons( port );
     70 
     71     int listenfd = socket( PF_INET, SOCK_STREAM, 0 );
     72     assert( listenfd >= 0 );
     73 
     74     //int nReuseAddr = 1;
     75     //setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR, &nReuseAddr, sizeof( nReuseAddr ) );
     76     ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) );
     77     if( ret == -1 )
     78     {
     79         printf( "errno is %d
    ", errno );
     80         return 1;
     81     }
     82     //assert( ret != -1 );
     83 
     84     ret = listen( listenfd, 5 );
     85     assert( ret != -1 );
     86 
     87     epoll_event events[ MAX_EVENT_NUMBER ];
     88     int epollfd = epoll_create( 5 );
     89     assert( epollfd != -1 );
     90     addfd( epollfd, listenfd );
     91 
     92     ret = socketpair( PF_UNIX, SOCK_STREAM, 0, pipefd );
     93     assert( ret != -1 );
     94     setnonblocking( pipefd[1] );
     95     addfd( epollfd, pipefd[0] );
     96 
     97     // add all the interesting signals here
     98     addsig( SIGHUP );
     99     addsig( SIGCHLD );
    100     addsig( SIGTERM );
    101     addsig( SIGINT );
    102     printf("SIGHUP:%d, SIGCHLD:%d, SIGTERM:%d, SIGINT:%d
    ", SIGHUP, SIGCHLD, SIGTERM, SIGINT);
    103     bool stop_server = false;
    104 
    105     while( !stop_server )
    106     {
    107         int number = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, -1 );
    108         if ( ( number < 0 ) && ( errno != EINTR ) )
    109         {
    110             printf( "epoll failure
    " );
    111             break;
    112         }
    113     
    114         for ( int i = 0; i < number; i++ )
    115         {
    116             int sockfd = events[i].data.fd;
    117             if( sockfd == listenfd )
    118             {
    119                 struct sockaddr_in client_address;
    120                 socklen_t client_addrlength = sizeof( client_address );
    121                 int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );
    122                 addfd( epollfd, connfd );
    123             }
    124             else if( ( sockfd == pipefd[0] ) && ( events[i].events & EPOLLIN ) )
    125             {
    126                 int sig;
    127                 char signals[1024];
    128                 ret = recv( pipefd[0], signals, sizeof( signals ), 0 );
    129                 if( ret == -1 )
    130                 {
    131                     continue;
    132                 }
    133                 else if( ret == 0 )
    134                 {
    135                     continue;
    136                 }
    137                 else
    138                 {
    139                     for( int i = 0; i < ret; ++i )
    140                     {
    141                         printf( "I caugh the signal %d
    ", signals[i] );
    142                         switch( signals[i] )
    143                         {
    144                             case SIGCHLD:
    145                             case SIGHUP:
    146                             {
    147                                 continue;
    148                             }
    149                             case SIGTERM: // kill pid
    150                             case SIGINT: // 键盘Ctrl+C
    151                             {
    152                                 stop_server = true;
    153                             }
    154                         }
    155                     }
    156                 }
    157             }
    158             else
    159             {
    160             }
    161         }
    162     }
    163 
    164     printf( "close fds
    " );
    165     close( listenfd );
    166     close( pipefd[1] );
    167     close( pipefd[0] );
    168     return 0;
    169 }
    View Code

    运行:

    [zf@localhost 10]$ ./a.out 127.0.0.1 1236
    SIGHUP:1, SIGCHLD:17, SIGTERM:15, SIGINT:2
    ^CI caugh the signal 2 (执行Ctrl + C)
    close fds
    [zf@localhost 10]$ ./a.out 127.0.0.1 1237
    SIGHUP:1, SIGCHLD:17, SIGTERM:15, SIGINT:2
    I caugh the signal 15 (被kill杀死)
    close fds

    2.信号函数

    #include <signal.h>
    
    int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
     struct sigaction {
                   void     (*sa_handler)(int); // 信号处理函数
                   void     (*sa_sigaction)(int, siginfo_t *, void *);
                   sigset_t   sa_mask; // 信号掩码
                   int        sa_flags; // 设置信号行为
                   void     (*sa_restorer)(void);
               };
    signum:信号类型
    act: 新的信号处理
    oact:返回之前的信号处理

    3.处理tcp带外数据:处理SIGURG
    server:
    #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, '', BUF_SIZE );
        int ret = recv( connfd, buffer, BUF_SIZE-1, MSG_OOB );
        printf( "got %d bytes of oob data '%s'
    ", ret, buffer );
    
        errno = save_errno;
    }
    
    void addsig( int sig, void ( *sig_handler )( int ) )
    {
        struct sigaction sa;
        memset( &sa, '', 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
    ", 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
    ", errno );
        }
        else
        {
            addsig( SIGURG, sig_urg );
            fcntl( connfd, F_SETOWN, getpid() );
    
            char buffer[ BUF_SIZE ];
            while( 1 )
            {
                memset( buffer, '', BUF_SIZE );
                ret = recv( connfd, buffer, BUF_SIZE-1, 0 );
                if( ret <= 0 )
                {
                    break;
                }
                printf( "got %d bytes of normal data '%s'
    ", ret, buffer );
            }
    
            close( connfd );
        }
    
        close( sock );
        return 0;
    }
    View Code

    client:

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    
    int main( int argc, char* argv[] )
    {
        if( argc <= 2 )
        {
            printf( "usage: %s ip_address port_number
    ", basename( argv[0] ) );
            return 1;
        }
        const char* ip = argv[1];
        int port = atoi( argv[2] );
    
        struct sockaddr_in server_address;
        bzero( &server_address, sizeof( server_address ) );
        server_address.sin_family = AF_INET;
        inet_pton( AF_INET, ip, &server_address.sin_addr );
        server_address.sin_port = htons( port );
    
        int sockfd = socket( PF_INET, SOCK_STREAM, 0 );
        assert( sockfd >= 0 );
        if ( connect( sockfd, ( struct sockaddr* )&server_address, sizeof( server_address ) ) < 0 )
        {
            printf( "connection failed
    " );
        }
        else
        {
            printf( "send oob data out
    " );
            const char* oob_data = "abc";
            const char* normal_data = "123";
            send( sockfd, normal_data, strlen( normal_data ), 0 );
            send( sockfd, oob_data, strlen( oob_data ), MSG_OOB );
            send( sockfd, normal_data, strlen( normal_data ), 0 );
        }
    
        close( sockfd );
        return 0;
    }
    View Code

    out:

    [zf@localhost 10]$ ./a.out 127.0.0.1 1234
    got 1 bytes of oob data 'c'
    got 5 bytes of normal data '123ab'
    got 3 bytes of normal data '123'


  • 相关阅读:
    Javascript 与 c# 数据加密互通 DEC
    Auto.js 隐藏日志信息、定时器
    Auto.js 检测开启无障碍
    Auto.js 初学碰到的坑
    SmartAssembly 汉化说明
    espcms 表结构说明
    处理器调度
    进程死锁与避免
    并发程序设计
    Mysql性能调优
  • 原文地址:https://www.cnblogs.com/vczf/p/14771634.html
Copyright © 2011-2022 走看看