Unix网络编程代码 第14章 高级I/O函数

来源:互联网 发布:nexvap电子烟 知乎 编辑:程序博客网 时间:2024/05/21 20:24

第14章 高级I/O函数

14.2 套接字超时

14.2.1 使用SIGALRM 为连接设置超时

#include<netinet/in.h>/* sockaddr_in{} and other Internet defns */#include<strings.h>#include<stdarg.h>/* ANSI C header file */#include<syslog.h>/* for syslog() */#include<stdlib.h>#include<errno.h>#include<stdio.h>#include<string.h>#include<unistd.h>#include<arpa/inet.h>#include<signal.h>#defineMAXLINE4096/* max text line length */#defineSAstruct sockaddrtypedef void Sigfunc(int);/* for signal handlers */void err_doit(int errnoflag, const char *fmt, va_list ap){int errno_save;char buf[MAXLINE];errno_save = errno;/* value caller might want printed */vsprintf(buf, fmt, ap);if (errnoflag)sprintf(buf + strlen(buf), ": %s", strerror(errno_save));strcat(buf, "\n");fflush(stdout);/* in case stdout and stderr are the same */fputs(buf, stderr);fflush(stderr);/* SunOS 4.1.* doesn't grok NULL argument */return;}void err_quit(const char *fmt, ...){va_list ap;va_start(ap, fmt);err_doit(0, fmt, ap);va_end(ap);exit(1);}void err_sys(const char *fmt, ...){va_list ap;va_start(ap, fmt);err_doit(1, fmt, ap);va_end(ap);exit(1);}Sigfunc *signal(int signo, Sigfunc * func){struct sigaction act, oact;act.sa_handler = func;sigemptyset(&act.sa_mask);act.sa_flags = 0;if (signo == SIGALRM) {#ifdefSA_INTERRUPTact.sa_flags |= SA_INTERRUPT;/* SunOS 4.x */#endif} else {#ifdefSA_RESTARTact.sa_flags |= SA_RESTART;/* SVR4, 44BSD */#endif}if (sigaction(signo, &act, &oact) < 0)return (SIG_ERR);return (oact.sa_handler);}Sigfunc *Signal(int signo, Sigfunc * func){/* for our signal() function */Sigfunc *sigfunc;if ((sigfunc = signal(signo, func)) == SIG_ERR)err_sys("signal error");return (sigfunc);}void err_msg(const char *fmt, ...){va_list ap;va_start(ap, fmt);err_doit(0, fmt, ap);va_end(ap);return;}void connect_alarm(int signo){printf("time out\n");return;/* just interrupt the connect() */}int connect_timeo(int sockfd, const SA * saptr, socklen_t salen, int nsec){Sigfunc *sigfunc;int n;sigfunc = Signal(SIGALRM, connect_alarm);if (alarm(nsec) != 0)err_msg("connect_timeo: alarm was already set");if ((n = connect(sockfd, saptr, salen)) < 0) {close(sockfd);if (errno == EINTR)errno = ETIMEDOUT;}alarm(0);/* turn off the alarm */Signal(SIGALRM, sigfunc);/* restore previous signal handler */return (n);}void Connect_timeo(int fd, const SA * sa, socklen_t salen, int sec){if (connect_timeo(fd, sa, salen, sec) < 0)err_sys("connect_timeo error");}int main(int argc, char **argv){int sockfd;struct sockaddr_in servaddr;if (argc != 2)err_quit("usage: a.out <IPaddress>");if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)err_sys("socket error");bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(13);/* daytime server */if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)err_quit("inet_pton error for %s", argv[1]);Connect_timeo(sockfd, (SA *) & servaddr, sizeof(servaddr), 5);exit(0);}

14.2.2 使用SIGALRM 为recvfrom设置超时

#include<netinet/in.h>/* sockaddr_in{} and other Internet defns */#include<strings.h>#include<stdarg.h>#include<stdlib.h>#include<stdio.h>#include<string.h>#include<errno.h>#include<arpa/inet.h>#include<signal.h>#include<unistd.h>#defineMAXLINE4096/* max text line length */#defineSERV_PORT 9877/* TCP and UDP */#defineSAstruct sockaddrtypedef void Sigfunc(int);/* for signal handlers */void err_doit(int errnoflag, const char *fmt, va_list ap){int errno_save;char buf[MAXLINE];errno_save = errno;/* value caller might want printed */vsprintf(buf, fmt, ap);if (errnoflag)sprintf(buf + strlen(buf), ": %s", strerror(errno_save));strcat(buf, "\n");fflush(stdout);/* in case stdout and stderr are the same */fputs(buf, stderr);fflush(stderr);/* SunOS 4.1.* doesn't grok NULL argument */return;}void err_quit(const char *fmt, ...){va_list ap;va_start(ap, fmt);err_doit(0, fmt, ap);va_end(ap);exit(1);}void err_sys(const char *fmt, ...){va_list ap;va_start(ap, fmt);err_doit(1, fmt, ap);va_end(ap);exit(1);}int Socket(int family, int type, int protocol){int n;if ((n = socket(family, type, protocol)) < 0)err_sys("socket error");return (n);}void Inet_pton(int family, const char *strptr, void *addrptr){int n;if ((n = inet_pton(family, strptr, addrptr)) < 0)err_sys("inet_pton error for %s", strptr);/* errno set */else if (n == 0)err_quit("inet_pton error for %s", strptr);/* errno not set *//* nothing to return */}char *Fgets(char *ptr, int n, FILE * stream){char *rptr;if ((rptr = fgets(ptr, n, stream)) == NULL && ferror(stream))err_sys("fgets error");return (rptr);}ssize_t Recvfrom(int fd, void *ptr, size_t nbytes, int flags, struct sockaddr * sa, socklen_t * salenptr){ssize_t n;if ((n = recvfrom(fd, ptr, nbytes, flags, sa, salenptr)) < 0)err_sys("recvfrom error");return (n);}void Sendto(int fd, const void *ptr, size_t nbytes, int flags,    const struct sockaddr *sa, socklen_t salen){if (sendto(fd, ptr, nbytes, flags, sa, salen) != (ssize_t) nbytes)err_sys("sendto error");}void Fputs(const char *ptr, FILE * stream){if (fputs(ptr, stream) == EOF)err_sys("fputs error");}Sigfunc *signal(int signo, Sigfunc * func){struct sigaction act, oact;act.sa_handler = func;sigemptyset(&act.sa_mask);act.sa_flags = 0;if (signo == SIGALRM) {#ifdefSA_INTERRUPTact.sa_flags |= SA_INTERRUPT;/* SunOS 4.x */#endif} else {#ifdefSA_RESTARTact.sa_flags |= SA_RESTART;/* SVR4, 44BSD */#endif}if (sigaction(signo, &act, &oact) < 0)return (SIG_ERR);return (oact.sa_handler);}Sigfunc *Signal(int signo, Sigfunc * func){/* for our signal() function */Sigfunc *sigfunc;if ((sigfunc = signal(signo, func)) == SIG_ERR)err_sys("signal error");return (sigfunc);}void sig_alrm(int signo){printf("time out\n");return;/* just interrupt the recvfrom() */}void dg_cli(FILE * fp, int sockfd, const SA * pservaddr, socklen_t servlen){int n;char sendline[MAXLINE], recvline[MAXLINE + 1];Signal(SIGALRM, sig_alrm);while (Fgets(sendline, MAXLINE, fp) != NULL) {Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr,       servlen);alarm(5);if ((n =     recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL)) < 0) {if (errno == EINTR)fprintf(stderr, "socket timeout\n");elseerr_sys("recvfrom error");} else {alarm(0);recvline[n] = 0;/* null terminate */Fputs(recvline, stdout);}}}int main(int argc, char **argv){int sockfd;struct sockaddr_in servaddr;if (argc != 2)err_quit("usage: udpcli <IPaddress>");bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(SERV_PORT);Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);sockfd = Socket(AF_INET, SOCK_DGRAM, 0);dg_cli(stdin, sockfd, (SA *) & servaddr, sizeof(servaddr));exit(0);}

14.2.3 使用select 为recvfrom设置超时

#include<netinet/in.h>/* sockaddr_in{} and other Internet defns */#include<strings.h>#include<sys/select.h>#include<stdarg.h>#include<stdlib.h>#include<stdio.h>#include<string.h>#include<errno.h>#include<arpa/inet.h>#defineMAXLINE4096/* max text line length */#defineSERV_PORT 9877/* TCP and UDP */#defineSAstruct sockaddrtypedef void Sigfunc(int);/* for signal handlers */void err_doit(int errnoflag, const char *fmt, va_list ap){int errno_save;char buf[MAXLINE];errno_save = errno;/* value caller might want printed */vsprintf(buf, fmt, ap);if (errnoflag)sprintf(buf + strlen(buf), ": %s", strerror(errno_save));strcat(buf, "\n");fflush(stdout);/* in case stdout and stderr are the same */fputs(buf, stderr);fflush(stderr);/* SunOS 4.1.* doesn't grok NULL argument */return;}void err_quit(const char *fmt, ...){va_list ap;va_start(ap, fmt);err_doit(0, fmt, ap);va_end(ap);exit(1);}void err_sys(const char *fmt, ...){va_list ap;va_start(ap, fmt);err_doit(1, fmt, ap);va_end(ap);exit(1);}int Socket(int family, int type, int protocol){int n;if ((n = socket(family, type, protocol)) < 0)err_sys("socket error");return (n);}void Inet_pton(int family, const char *strptr, void *addrptr){int n;if ((n = inet_pton(family, strptr, addrptr)) < 0)err_sys("inet_pton error for %s", strptr);/* errno set */else if (n == 0)err_quit("inet_pton error for %s", strptr);/* errno not set *//* nothing to return */}char *Fgets(char *ptr, int n, FILE * stream){char *rptr;if ((rptr = fgets(ptr, n, stream)) == NULL && ferror(stream))err_sys("fgets error");return (rptr);}ssize_t Recvfrom(int fd, void *ptr, size_t nbytes, int flags, struct sockaddr * sa, socklen_t * salenptr){ssize_t n;if ((n = recvfrom(fd, ptr, nbytes, flags, sa, salenptr)) < 0)err_sys("recvfrom error");return (n);}void Sendto(int fd, const void *ptr, size_t nbytes, int flags,    const struct sockaddr *sa, socklen_t salen){if (sendto(fd, ptr, nbytes, flags, sa, salen) != (ssize_t) nbytes)err_sys("sendto error");}void Fputs(const char *ptr, FILE * stream){if (fputs(ptr, stream) == EOF)err_sys("fputs error");}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));/* 4> 0 if descriptor is readable */}int Readable_timeo(int fd, int sec){int n;if ((n = readable_timeo(fd, sec)) < 0)err_sys("readable_timeo error");return (n);}void dg_cli(FILE * fp, int sockfd, const SA * pservaddr, socklen_t servlen){int n;char sendline[MAXLINE], recvline[MAXLINE + 1];while (Fgets(sendline, MAXLINE, fp) != NULL) {Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr,       servlen);if (Readable_timeo(sockfd, 5) == 0) {fprintf(stderr, "socket timeout\n");} else {n = Recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);recvline[n] = 0;/* null terminate */Fputs(recvline, stdout);}}}int main(int argc, char **argv){int sockfd;struct sockaddr_in servaddr;if (argc != 2)err_quit("usage: udpcli <IPaddress>");bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(SERV_PORT);Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);sockfd = Socket(AF_INET, SOCK_DGRAM, 0);dg_cli(stdin, sockfd, (SA *) & servaddr, sizeof(servaddr));exit(0);}

14.2.4 使用 SO_RCVTIMEO 为recvfrom 设置超时

#define __need_timeval#include<strings.h>#include<time.h>#include<netinet/in.h>/* sockaddr_in{} and other Internet defns */#include<stdarg.h>#include<stdlib.h>#include<stdio.h>#include<string.h>#include<errno.h>#include<arpa/inet.h>#defineMAXLINE4096/* max text line length */#defineSERV_PORT 9877/* TCP and UDP */#defineSAstruct sockaddrvoid err_doit(int errnoflag, const char *fmt, va_list ap){int errno_save;char buf[MAXLINE];errno_save = errno;/* value caller might want printed */vsprintf(buf, fmt, ap);if (errnoflag)sprintf(buf + strlen(buf), ": %s", strerror(errno_save));strcat(buf, "\n");fflush(stdout);/* in case stdout and stderr are the same */fputs(buf, stderr);fflush(stderr);/* SunOS 4.1.* doesn't grok NULL argument */return;}void err_quit(const char *fmt, ...){va_list ap;va_start(ap, fmt);err_doit(0, fmt, ap);va_end(ap);exit(1);}void err_sys(const char *fmt, ...){va_list ap;va_start(ap, fmt);err_doit(1, fmt, ap);va_end(ap);exit(1);}int Socket(int family, int type, int protocol){int n;if ((n = socket(family, type, protocol)) < 0)err_sys("socket error");return (n);}void Inet_pton(int family, const char *strptr, void *addrptr){int n;if ((n = inet_pton(family, strptr, addrptr)) < 0)err_sys("inet_pton error for %s", strptr);/* errno set */else if (n == 0)err_quit("inet_pton error for %s", strptr);/* errno not set *//* nothing to return */}char *Fgets(char *ptr, int n, FILE * stream){char *rptr;if ((rptr = fgets(ptr, n, stream)) == NULL && ferror(stream))err_sys("fgets error");return (rptr);}ssize_t Recvfrom(int fd, void *ptr, size_t nbytes, int flags, struct sockaddr * sa, socklen_t * salenptr){ssize_t n;if ((n = recvfrom(fd, ptr, nbytes, flags, sa, salenptr)) < 0)err_sys("recvfrom error");return (n);}void Sendto(int fd, const void *ptr, size_t nbytes, int flags,    const struct sockaddr *sa, socklen_t salen){if (sendto(fd, ptr, nbytes, flags, sa, salen) != (ssize_t) nbytes)err_sys("sendto error");}void Fputs(const char *ptr, FILE * stream){if (fputs(ptr, stream) == EOF)err_sys("fputs error");}void Setsockopt(int fd, int level, int optname, const void *optval,socklen_t optlen){if (setsockopt(fd, level, optname, optval, optlen) < 0)err_sys("setsockopt error");}void dg_cli(FILE * fp, int sockfd, const SA * pservaddr, socklen_t servlen){int n;char sendline[MAXLINE], recvline[MAXLINE + 1];struct timeval tv;tv.tv_sec = 5;tv.tv_usec = 0;Setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));while (Fgets(sendline, MAXLINE, fp) != NULL) {Sendto(sockfd, sendline, strlen(sendline), 0, pservaddr,       servlen);n = recvfrom(sockfd, recvline, MAXLINE, 0, NULL, NULL);if (n < 0) {if (errno == EWOULDBLOCK) {fprintf(stderr, "socket timeout\n");continue;} elseerr_sys("recvfrom error");}recvline[n] = 0;/* null terminate */Fputs(recvline, stdout);}}int main(int argc, char **argv){int sockfd;struct sockaddr_in servaddr;if (argc != 2)err_quit("usage: udpcli <IPaddress>");bzero(&servaddr, sizeof(servaddr));servaddr.sin_family = AF_INET;servaddr.sin_port = htons(SERV_PORT);Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);sockfd = Socket(AF_INET, SOCK_DGRAM, 0);dg_cli(stdin, sockfd, (SA *) & servaddr, sizeof(servaddr));exit(0);}

原创粉丝点击