首页 > 其他分享 >带有超时的udp客户端

带有超时的udp客户端

时间:2022-09-30 13:12:07浏览次数:52  
标签:udp 超时 int rset tv maxline sendline include 客户端

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>

static int sig_alrm(int);
 
const int maxline=4096;

int readable_timeo(int fd, int sec) {
	fd_set rset;
	struct timeval tv;
	FD_ZERO(&rset);
	FD_SET(fd, &rset);

	tv.tv_sec=sec;
	tv.tv_usec=0;

	return select(fd+1, &rset, NULL, NULL, &tv);
}

void dg_cli(FILE *fp, int sockfd, const struct sockaddr * pservaddr, socklen_t servlen) {
    int n;
    char sendline[maxline], recvline[maxline+1];
    char errbuff[maxline];

    while(fgets(sendline, maxline, fp) != NULL) {
        if(sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen)<0) {
            strerror_r(errno, errbuff, maxline);
            fprintf(stderr, "sendto error: %s\n", errbuff);
            exit(-1);
        }

        if((n=recvfrom(sockfd, recvline, maxline, 0, NULL, NULL))<0) {
            strerror_r(errno, errbuff, maxline);
            fprintf(stderr, "recvfrom error: %s\n", errbuff);
            exit(-1);
        }

        recvline[n]=0;
        fputs(recvline, stdout);
    }
}

void dg_cli_so(FILE *fp, int sockfd, const struct sockaddr * pservaddr, socklen_t servlen) {
    int n;
    char sendline[maxline], recvline[maxline+1];
    char errbuff[maxline];
    struct timeval tv;

    tv.tv_sec=5;
    tv.tv_usec=0;

    if(setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv))==-1) {
	    strerror_r(errno, errbuff, maxline);
            fprintf(stderr, "setsockopt error: %s\n", errbuff);
            exit(-1);
    }

    while(fgets(sendline, maxline, fp) != NULL) {
        if(sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen)<0) {
            strerror_r(errno, errbuff, maxline);
            fprintf(stderr, "sendto error: %s\n", errbuff);
            exit(-1);
        }

        n=recvfrom(sockfd, recvline, maxline, 0, NULL, NULL);
	if(n<0) {
		if(errno==EWOULDBLOCK) {
			fprintf(stderr, "socket timeout\n");
			continue;
		} else {
			strerror_r(errno, errbuff, maxline);
			fprintf(stderr, "recvfrom error: %s\n", errbuff);
			exit(-1);
		}
	}

	recvline[n]=0;
	fputs(recvline, stdout);
    }
}

void dg_cli_select(FILE *fp, int sockfd, const struct sockaddr * pservaddr, socklen_t servlen) {
    int n;
    char sendline[maxline], recvline[maxline+1];
    char errbuff[maxline];

    while(fgets(sendline, maxline, fp) != NULL) {
	    if(sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen)<0) {
		    strerror_r(errno, errbuff, maxline);
		    fprintf(stderr, "sendto error: %s\n", errbuff);
		    exit(-1);
	    }
	    
	    if(readable_timeo(sockfd, 5)==0) {
		    fprintf(stderr, "socket timeout\n");
	    } else {
		    if((n=recvfrom(sockfd, recvline, maxline, 0, NULL, NULL))<0) {
			    strerror_r(errno, errbuff, maxline);
			    fprintf(stderr, "recvfrom error: %s\n", errbuff);
			    exit(-1);
		    }
		    
		    recvline[n]=0;
		    fputs(recvline, stdout);
	    }
    }
}

void dg_cli_alrm(FILE *fp, int sockfd, const struct sockaddr * pservaddr, socklen_t servlen) {
    int n;
    char sendline[maxline], recvline[maxline+1];
    char errbuff[maxline];

    if(signal(SIGALRM, sig_alrm)<0) {
	    strerror_r(errno, errbuff, maxline);
	    fprintf(stderr, "signal error: %s\n", errbuff);
	    exit(-1);
    }

    while(fgets(sendline, maxline, fp) != NULL) {
        if(sendto(sockfd, sendline, strlen(sendline), 0, pservaddr, servlen)<0) {
            strerror_r(errno, errbuff, maxline);
            fprintf(stderr, "sendto error: %s\n", errbuff);
            exit(-1);
        }

	alarm(5);
	
	if((n=recvfrom(sockfd, recvline, maxline, 0, NULL, NULL))<0) {
		if(errno==EINTR) {
			fprintf(stderr, "socket timeout\n");
		} else {
			strerror_r(errno, errbuff, maxline);
			fprintf(stderr, "recvfrom error: %s\n", errbuff);
			exit(-1);
		}
	} else {
		alarm(0);
		recvline[n]=0;
		fputs(recvline, stdout);
	}
    }
}
 
int main(int argc, char **argv) {
    int sockfd, n;
    char recvline[maxline+1], errbuff[maxline];
    struct sockaddr_in servaddr;
 
    if(argc != 2) {
        fprintf(stderr, "usage: a.out <IPaddress>\n");
        exit(-1);
    }
 
    if((sockfd=socket(AF_INET, SOCK_DGRAM, 0))<0) {
        strerror_r(errno, errbuff, maxline);
        fprintf(stderr, "socket error: %s\n", errbuff);
        exit(-1);
    }
 
    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family=AF_INET;
    servaddr.sin_port=htons(9999);
    if(inet_pton(AF_INET, argv[1], &servaddr.sin_addr)<=0) {
        fprintf(stderr, "inet_pton error for %s", argv[1]);
        exit(-1);
    }

    dg_cli_so(stdin, sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
     
    return 0;
}

static int sig_alrm(int signo) {
	printf("signal alarm\n");
	exit -1;
}

  

标签:udp,超时,int,rset,tv,maxline,sendline,include,客户端
From: https://www.cnblogs.com/donggongdechen/p/16744582.html

相关文章