• UDP信号驱动IO


    SIGIO信号

    信号驱动式I/O不适用于TCP套接字, 因为产生的信号过于频繁且不能准确判断信号产生的原因.
    设置信号驱动需把sockfd的非阻塞与信号驱动属性都打开

    server

    sockfd单独提出来作为全局变量, 便于sig_io处理函数访问
    num变量用于设置当前可读数据报数量
    struct data结构作为信号处理函数中保存客户端信息的记录地址

    #include <unistd.h>
    #include <fcntl.h>
    #include <signal.h>
    #include <string.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/ioctl.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #define MAXLINE 1024
    #define SERV_PORT 5555
    void err_quit(const char *s){
        perror(s);
        exit(1);
    }
    
    int sockfd;
    
    struct data{
        struct sockaddr addr;
        char data[1024];
    }DATA;
    static int num=0;
    
    void sig_io(int signo){
        ssize_t nread;
    
        char *buff=DATA.data;
        int size=sizeof(DATA.data);
        socklen_t slen=sizeof(DATA.addr);
        nread=recvfrom(sockfd,buff,size,0,&DATA.addr,&slen);
    
        if(nread < 0){
            if(errno == EWOULDBLOCK)
                return;
            else
                err_quit("recvfrom");
        }
        buff[nread]=0;
        num++;
    }
    
    int main(int argc,char *argv[]){
        struct sockaddr_in servaddr;
        sockfd=socket(AF_INET,SOCK_DGRAM,0);
        bzero(&servaddr,sizeof(servaddr));
        servaddr.sin_family=AF_INET;
        servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
        servaddr.sin_port=htons(SERV_PORT);
        if(bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)) < 0)
            err_quit("bind");
    
        int on = 1;
        signal(SIGIO,sig_io);
        fcntl(sockfd,F_SETOWN,getpid());
        ioctl(sockfd,FIOASYNC,&on);
        ioctl(sockfd,FIONBIO,&on);
    
        sigset_t zeromask,newmask,oldmask;
        sigemptyset(&zeromask);
        sigemptyset(&newmask);
        sigemptyset(&oldmask);
        sigaddset(&newmask,SIGIO);
    
        sigprocmask(SIG_BLOCK,&newmask,&oldmask);
        for(;;){
            while(num == 0)
                sigsuspend(&zeromask);
    
            sigprocmask(SIG_SETMASK,&oldmask,NULL);
            sendto(sockfd,DATA.data,strlen(DATA.data),0,&DATA.addr,sizeof(DATA.addr));
            sigprocmask(SIG_BLOCK,&newmask,&oldmask);
            if(num > 0)
                num--;
        }
        return 0;
    }
    

    客户端

    客户端只要实现发送一次然后接受一次即可, 略

  • 相关阅读:
    struts的ognl.NoConversionPossible错误
    hibernate many-to-one
    向网页中插入百度地图
    hibernate多对一单向配置
    PHP+MySQL按时间段查询记录代码
    iis无法启动的解决办法-卸掉KB939373补丁
    跳转回上一页代码
    QQ在线客服代码
    SSH(Struts2 + Hibernate + Spring)嵌入 KindEditor(KE)
    php从数据库选取记录形成列表(首页调用)
  • 原文地址:https://www.cnblogs.com/cfans1993/p/6598331.html
Copyright © 2020-2023  润新知