Linux网络编程的相关信号

《Linux高性能服务器编程》阅读笔记:

  SIGHUP、SIGPIPE和SIGURG是网络编程中密切相关的信号。

  SIGHUP: SIGHUP信号的触发时机是在进程的控制终端被挂起,对于没有控制终端的网络后台程序来说,通常是利用SIGHUP信号来强制服务器程序重读相关的配置文件,一个典型的例子就是xinetd超级服务器程序。

  SIGPIPE: 往读端关闭的管道或socket连接中写数据将会触发SIGPIPE信号,在Linux网络编程基础API–TCP的数据读写API中讲道,对端close()通信连接后,本端继续发数据,本端将会收到一个RST复位报文提示本端对端已经关闭连接、需重新建立连接,此时再继续往对端发数据,本端系统将会产生SIFPIPE信号。服务器程序需要在代码中捕获并处理该信号,或者至少忽略它,因为SIGPIPE信号的默认处理行为是结束所在进程。引起SIGPIPE信号的写操作将设置errno为EPIPE。send()系统调用的MSG_NOSIGNAL可选项可禁止写操作触发SPGPIPE信号,所以在这种情况下可以使用send()函数反馈的errno值来判断管道或者socket连接的对端是否关闭。
  此外,前面学习IO复用时讲道,IO复用也可以用来检测管道和socket连接的读(对)端是否已经关闭,如poll,当读对端关闭时,本(写)端描述符的POLLHUP事件将被触发,当socket连接被对端关闭时,socket上的POLLRDHUP事件将被触发。

  SIGURG:在前面的IO复用技术中,select()等系统调用在接收到带外数据时将能够返回并返回异常事件(select()是exceptfds),另一种方法就是利用SIGURG信号:

typedef void(*handle_func)(int);

//SIGURG的信号处理函数,负责读带外数据
void sig_urg(int sig)
{
    int errno_bak = errno;
    char buf[BUFZE] = {0};
    int ret = recv(connfd, buf, BUFSE - 1, MSG_OOB);
    printf("%d byte OOB data: %s\n", ret, buf);
    errno = errno_bak;
}

//为SIGURG信号绑定操作函数等行为
int add_signal(int sig, handle_func func)
{
    struct sigaction sa;
    bzero(&sa, sizeof(sa));
    sa.sa_handler = func;
    sa.sa_flags |= SA_RESTART;  //重新调用被该信号终止的系统调用,保证服务端程序一直运行
    sigfillset(&sa.sa_mask);    //屏蔽其它所有所有信号

    return sigaction(sig, &sa, NULL);
}

int main(void)
{
    //...

    add_signal(SIGURG, sig_urg);        //注册信号捕捉函数
    fcntl(connfd, F_SETOWN, getpid());  //设置SIGURG信号关联的fd的宿主进程或进程组

    char buf[BUFSE] = {0};

    while (1)   //循环读数据
    {
        bzeor(buf, BUFSZ);
        ret = recv(connfd, buf, BUFSZ - 1, 0);
        if (ret <= 0)
            break;

        printf("%d byte Normal data: %s\n", ret, buf);
    }
    close(fd);
    close(sock_fd);
    return 0;
}

你可能感兴趣的:(Linux系统/网络编程,Linux编程)