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'


  • 相关阅读:
    VS2008 环境中完美搭建 Qt 4.7.4 静态编译的调试与发布 Inchroy's Blog 博客频道 CSDN.NET
    编写可丢弃的代码
    c++ using namespace std; 海明威 博客园
    解决MySQL server has gone away
    nginx upstream 调度策略
    (2006, 'MySQL server has gone away') 错误解决 dba007的空间 51CTO技术博客
    Linux IO模型漫谈(2) 轩脉刃 博客园
    redis源码笔记 initServer 刘浩de技术博客 博客园
    MySQLdb批量插入数据
    词库的扩充百度百科的抓取你知道这些热词吗? rabbit9898 ITeye技术网站
  • 原文地址:https://www.cnblogs.com/vczf/p/14771634.html
Copyright © 2011-2022 走看看