关于Linuxsocket编程的SIGURG信号

liuscmail 2011-01-05 11:06:23
看到过类似的问题在csdn中,但是最后没人给出结果,所以在发一下吧

为了学习和研究实验了一下socket中带外数据,发现客户端发送OOB数据不能在服务端引发SIGURG信号。
只是在一些资料上看到当有OOB数据到来是,服务端进程会引发SIGURG信号,但是客户端自己发送的OOB数据,用send(MSG_OOB)发送的,但是在服务端看不到这个信号产生,只有一个进程,在进程里面也注册了,fd的宿主,但是看不到信号处理函数被调用。

所以感觉有点奇怪,还是发送OOB数据,需要在服务端吧socket设置成异步的吗,没有看到那个资料上这样说,只是看到当是异步socket时,socket会发送SIGIO信号

希望那个高人能够指点一下,怎么样才能让服务端产生SIGURG信号,需要那么特殊的设置,是不是这样简单的注册一下SIGURG信号的处理函数就可以了。。。。
...全文
578 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
lingq6715 2013-03-27
  • 打赏
  • 举报
回复
用kill模拟触发 kill(getpid(),SIGURG);
lingq6715 2013-03-27
  • 打赏
  • 举报
回复
用kill模拟触发
caploveleo 2013-02-27
  • 打赏
  • 举报
回复
使用signal和sigaction都试过了,都没有反应。。。 服务端始终触发不了SIGURG信号,各位帮忙瞅瞅了,上面时服务端和客户端代码。。。
caploveleo 2013-02-27
  • 打赏
  • 举报
回复
//server.c


#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
/* 服务器要监听的本地端口*/
#define MYPORT 4000
/* 能够同时接受多少没有accept 的连接*/
#define BACKLOG 10

int new_fd;

void sig_urg(int signo);
void main()
{
    /* 在sock_fd 上进行监听,new_fd 接受新的连接*/
    int sock_fd;
    /* 用于存储以前系统缺省的SIGURL 处理器的变量*/ void * old_sig_urg_handle ;
    /* 自己的地址信息*/
    struct sockaddr_in my_addr;
    /* 连接者的地址信息*/
    struct sockaddr_in their_addr;
    int sin_size;
    int n ;
    char buff[100] ;
    int pid;
    int new_id;
    struct sigaction curract, oldact;

    /* 这里就是我们一直强调的错误检查.如果调用socket() 出错,则返回*/
    if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        /* 输出错误提示并退出*/
        perror("socket");
        exit(1);
    }
    /* 主机字节顺序*/
    my_addr.sin_family = AF_INET;
    /* 网络字节顺序,短整型*/
    my_addr.sin_port = htons(MYPORT);
    /* 将运行程序机器的IP 填充入s_addr */
    my_addr.sin_addr.s_addr = INADDR_ANY;
    /* 将此结构的其余空间清零*/
    bzero(&(my_addr.sin_zero), 8);
    /* 这里是我们一直强调的错误检查!! */
    if (bind(sock_fd, (struct sockaddr *)&my_addr,sizeof(struct sockaddr)) == -1)
    {
        /* 如果调用bind()失败,则给出错误提示,退出*/
        perror("bind");
        exit(1);
    }
    /* 这里是我们一直强调的错误检查!! */
    if (listen(sock_fd, BACKLOG) == -1)
    {
        /* 如果调用listen 失败,则给出错误提示,退出*/
        perror("listen");
        exit(1);
    }
    /* 设置SIGURG 的处理函数 sig_urg */
    old_sig_urg_handle = signal(SIGURG, sig_urg);
    /* 更改connfd 的属主*/
    fcntl(sock_fd, F_SETOWN, getpid());

//    curract.sa_handler = sig_urg;
//    curract.sa_flags = 0;
//    sigemptyset(&curract.sa_mask);
//    sigaction(SIGURG, &curract, &oldact);

    while(1)
    {
        /* 这里是主accept()循环*/
        sin_size = sizeof(struct sockaddr_in);
        /* 这里是我们一直强调的错误检查!! */
        if ((new_fd = accept(sock_fd, (struct sockaddr *)&their_addr, &sin_size)) == -1)
        {
            perror("accept");
            continue;
        }

        /* 服务器给出出现连接的信息*/
        printf("server: got connection from %s\n", inet_ntoa(their_addr.sin_addr));
        /* 这里将建立一个子进程来和刚刚建立的套接字进行通讯*/
        pid = fork();
        if(pid < 0) {
            perror("fork error");
        } else if (pid == 0) {
            /* 这里是子进程*/
            while(1)
            {
                if((n = recv(new_fd, buff, sizeof(buff) - 1, 0)) == 0)
                {
                        printf("received EOF\n");
                        break ;
                }
                buff[n] = 0 ;
                printf("Recv %d bytes: %s\n", n, buff);
            }
        }
        if(pid > 0) {
            /* 等待所有的子进程都退出*/
            new_id = waitpid(-1, NULL, WNOHANG);
//            sigaction(SIGURG, &oldact, NULL);
            /* 恢复系统以前对SIGURG 的处理器*/
            signal(SIGURG, old_sig_urg_handle);
            /* 关闭new_fd 代表的这个套接字连接*/
            close(new_fd);
        }
    }
}

void sig_urg(int signo)
{
    int n;
    char buff[100] ;
    printf("SIGURG received\n");
    n = recv(new_fd, buff, sizeof(buff) - 1, MSG_OOB);
    buff [ n ] = 0 ;
    printf("recv %d OOB byte: %s\n" , n,buff);
}
//client.c

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
/* 服务器程序监听的端口号*/
#define PORT 4000
/* 我们一次所能够接收的最大字节数*/
#define MAXDATASIZE 100
int main(int argc, char *argv[])
{
    /* 套接字描述符*/
    int sockfd, new_fd;
    char buf[MAXDATASIZE];
    struct hostent *he;
    /* 连接者的主机信息*/
    struct sockaddr_in their_addr;
    /* 检查参数信息*/
    if (argc != 2)
    {
        /* 如果没有参数,则给出使用方法后退出*/
        fprintf(stderr,"usage: client hostname\n");
        exit(1);
    }
    /* 取得主机信息*/
    if ((he=gethostbyname(argv[1])) == NULL)
    {
        /* 如果gethostbyname()发生错误,则显示错误信息并退出*/
        herror("gethostbyname");
        exit(1);
    }
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        /* 如果socket()调用出现错误则显示错误信息并退出*/
        perror("socket");
        exit(1);
    }
    /* 主机字节顺序*/
    their_addr.sin_family = AF_INET;
    /* 网络字节顺序,短整型*/
    their_addr.sin_port = htons(PORT);
    their_addr.sin_addr = *((struct in_addr *)he->h_addr);
    printf("%s\n", inet_ntoa(*((struct in_addr *)he->h_addr)));
    /* 将结构剩下的部分清零*/
    bzero(&(their_addr.sin_zero), 8);
    if((connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1)
    {
        /* 如果connect()建立连接错误,则显示出错误信息,退出*/
        perror("connect");
        exit(1);
    }
    /* 这里就是我们说的错误检查! */
    if (send(sockfd, "123", 3, 0) == -1)
    {
        /* 如果错误,则给出错误提示,然后关闭这个新连接,退出*/
        perror("send");
        close(sockfd);
        exit(0);
    }
    printf("Send 3 byte of normal data\n");
    /* 睡眠1 秒*/
    sleep(1);
    if (send(sockfd, "4", 1, MSG_OOB)== -1)
    {
        perror("send");
        close(sockfd);
        exit(0);
    }
    printf("Send 1 byte of OOB data\n");
    sleep(1);
    if (send(sockfd, "56", 2, 0) == -1)
    {
        perror("send");
        close(sockfd);
        exit(0);
    }
    printf("Send 2 bytes of normal data\n");
    sleep(1);
    if(send(sockfd,"7", 1, MSG_OOB)== -1)
    {
        perror("send");
        close(sockfd);
        exit(0);
    }
    printf("Send 1 byte of OOB data\n");
    sleep(1);
    if (send(sockfd, "89", 2, MSG_OOB)== -1)
    {
        perror("send");
        close(sockfd);
        exit(0);
    }
    printf("Send 2 bytes of normal data\n");
    sleep(1);
    close(sockfd);
    return 0;
}
yutaooo 2011-01-06
  • 打赏
  • 举报
回复

还要这样吧:

fcntl(sockfd, F_SETOWN, getpid());
justkk 2011-01-06
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 yutaooo 的回复:]
还要这样吧:

fcntl(sockfd, F_SETOWN, getpid());
[/Quote]+1
justkk 2011-01-06
  • 打赏
  • 举报
回复
贴代码看看,大家也可以试试
wickyboy 2011-01-06
  • 打赏
  • 举报
回复
你的信号处理程序是在哪里注册的,是在accept之前注册的吗?

如果不是,那么就有可能是带外数据在accept返回之前到达,所以接收不到信号通知
liuscmail 2011-01-06
  • 打赏
  • 举报
回复
设置过了还是不行啊,不知道怎么搞的

23,118

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧