信号驱动方式处理UDP数据

来源:互联网 发布:用友网络股票分析 编辑:程序博客网 时间:2024/05/16 06:00

server端代码:

/*
UDP服务器
说明:用于在sigio信号处理程序中接收来自数据报客户端发来的数据报,接到的数据报存放
在一个队列中,随后程序主循环将从此队列中读取数据并进行处理。
用法:./server ip portnumber
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/ioctl.h>
#define MAX_LENTH 1500

static int nqueue = 0 ;
void sigio_handler (int signum) //信号处理函数
{
    if(signum == SIGIO){
        nqueue++;
        printf("signum=%d,nqueue=%d\n",signum, nqueue);
        return;
    }
}

static recv_buf[MAX_LENTH];             //接收数据的数组
      
int main (int argc, char* argv[])
{
    int sockfd, on = 1;
    struct sigaction action;
    sigset_t newmask, oldmask;
    struct sockaddr_in ser_addr;
    if(argc != 3){                         //执行程序时需要输入三个参数
        printf("use: %s ip add port\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    
    memset(&ser_addr, 0, sizeof(ser_addr));   //将结构体置零
    ser_addr.sin_family = AF_INET;         //IPv4协议簇
    ser_addr.sin_port = htons(atoi(argv[2]));    //端口号
    if(inet_aton(argv[1], (struct in_addr*) &ser_addr.sin_addr.s_addr) == 0){       //读取IP地址
        perror("argv[1]");
        exit(EXIT_FAILURE);
    }    
    
    if(-1 == (sockfd = (socket(AF_INET, SOCK_DGRAM, 0)))){   //创建socket
        perror("Create socket failed");
        exit(EXIT_FAILURE);
    }
    
    if(-1 == (bind(sockfd, (struct sockaddr *) &ser_addr, sizeof(ser_addr)))){
        perror("Bind socket failed");
        exit(EXIT_FAILURE);
    }

    memset(&action, 0, sizeof(action));
    action.sa_handler = sigio_handler;
    action.sa_flags = 0;
    sigaction(SIGIO, &action, NULL);     //安装信号
    
    if(-1 == fcntl(sockfd, F_SETOWN, getpid())){    //设置socket的拥有者
        perror("Fcnt1 F_SETOWN");
        exit(EXIT_FAILURE);
    }
    if(-1 == ioctl(sockfd, FIOASYNC, &on)){
        perror("Ioctl FIOASYNC");
        exit(EXIT_FAILURE);
    }
    
    sigemptyset(&oldmask);
    sigemptyset(&newmask);
    sigaddset(&newmask, SIGIO);
    printf("get ready\n");
    
    while(1){
        int len;
        sigprocmask(SIG_BLOCK, &newmask, &oldmask);
        while(nqueue == 0)
            sigsuspend(&oldmask);
        memset(&recv_buf, '\0', MAX_LENTH);
        len = recv(sockfd, recv_buf, MAX_LENTH, MSG_DONTWAIT);
        if(len == -1 && errno == EAGAIN){
            nqueue = 0;
        }    
        sigprocmask(SIG_SETMASK, &oldmask, NULL);
        if(len > 0){
            printf("recv %d byte(s), msg is %s\n",len, recv_buf);
        }

    }
}


client代码:

 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
 #include <signal.h>
 #include <errno.h>
 #include <time.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <netdb.h>
 #include <arpa/inet.h>
 #include <fcntl.h>
 #include <string.h>
 #include <netinet/in.h>
 #include <sys/ioctl.h>
 #define MAX_LENTH 1500
int main (int argc, char * argv[])
{
    struct sockaddr_in addr;
    int sock_fd, ret;
    char snd_buf[MAX_LENTH];
    if(argc != 3){
        printf("use:%s ip_add port\n",argv[0]);
        exit(EXIT_FAILURE);
    }
    memset(&addr, 0, sizeof(struct socketaddr_in*));
    addr.sin_family = AF_INET;
    if(0 == inet_aton(argv[1], (struct in_addr*) &addr.sin_addr.s_addr)){
        perror("argv[1]");
        exit(EXIT_FAILURE);
    }
    addr.sin_port = htons(atoi(argv[2]));
    
    if(-1 == (sock_fd = socket(AF_INET, SOCK_DGRAM, 0))){
        printf("Create socket failed\n");
        exit(EXIT_FAILURE);
    }

    if(-1 == (ret = connect(sock_fd, (struct sockaddr*) &addr, sizeof(addr)))){
        perror("Connect failed");
        exit(EXIT_FAILURE);
    }
    while(1){
        printf("input msg to send:");
        memset(&snd_buf, '\0', MAX_LENTH);
        int i =0;
        fgets(snd_buf, MAX_LENTH - 1, stdin);
        write(sock_fd, snd_buf, MAX_LENTH - 1);
        //sendto(sock_fd,snd_buf, MAX_LENTH -1, 0 ,(struct sockaddr_in*)&addr, sizeof(struct sockaddr_in));
        printf("send message %d:%s",i++,snd_buf);
    }
}

原创粉丝点击