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'


原文地址:https://www.cnblogs.com/vczf/p/14771634.html