Unix网络编程代码 第7章 套接字选项

来源:互联网 发布:淘宝无法点击立即购买 编辑:程序博客网 时间:2024/05/16 06:14

第7章 套接字选项

7.3 检查选项是否受支持并获取默认值

#define __need_timeval#include<stdio.h>#include<time.h>#include<netinet/tcp.h>/* for TCP_xxx defines */#include<sys/socket.h>#include<netinet/in.h>/* sockaddr_in{} and other Internet defns */#include<string.h>#include<stdlib.h>#include<errno.h>#include<syslog.h>/* for syslog() */#include<stdarg.h>/* ANSI C header file */#include<unistd.h>#defineMAXLINE4096/* max text line length */int daemon_proc;/* set nonzero by daemon_init() */union val {int i_val;long l_val;struct linger linger_val;struct timeval timeval_val;} val;static char strres[128];char *sock_str_flag(union val *ptr, int len){/* *INDENT-OFF* */if (len != sizeof(int))snprintf(strres, sizeof(strres), "size (%d) not sizeof(int)", len);elsesnprintf(strres, sizeof(strres), "%s", (ptr->i_val == 0) ? "off" : "on");return (strres);/* *INDENT-ON* */}char *sock_str_int(union val *ptr, int len){if (len != sizeof(int))snprintf(strres, sizeof(strres), "size (%d) not sizeof(int)", len);elsesnprintf(strres, sizeof(strres), "%d", ptr->i_val);return (strres);}char *sock_str_linger(union val *ptr, int len){struct linger *lptr = &ptr->linger_val;if (len != sizeof(struct linger))snprintf(strres, sizeof(strres), "size (%d) not sizeof(struct linger)", len);elsesnprintf(strres, sizeof(strres), "l_onoff = %d, l_linger = %d", lptr->l_onoff, lptr->l_linger);return (strres);}char *sock_str_timeval(union val *ptr, int len){struct timeval *tvptr = &ptr->timeval_val;if (len != sizeof(struct timeval))snprintf(strres, sizeof(strres), "size (%d) not sizeof(struct timeval)", len);elsesnprintf(strres, sizeof(strres), "%ld sec, %ld usec", tvptr->tv_sec, tvptr->tv_usec);return (strres);}struct sock_opts {const char *opt_str;int opt_level;int opt_name;char *(*opt_val_str) (union val *, int);} sock_opts[] = {{"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, sock_str_flag}, {"SO_DEBUG", SOL_SOCKET, SO_DEBUG, sock_str_flag}, {"SO_DONTROUTE", SOL_SOCKET, SO_DONTROUTE, sock_str_flag}, {"SO_ERROR", SOL_SOCKET, SO_ERROR, sock_str_int}, {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, sock_str_flag}, {"SO_LINGER", SOL_SOCKET, SO_LINGER, sock_str_linger}, {"SO_OOBINLINE", SOL_SOCKET, SO_OOBINLINE, sock_str_flag}, {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, sock_str_int}, {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, sock_str_int}, {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, sock_str_int}, {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, sock_str_int}, {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, sock_str_timeval}, {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, sock_str_timeval}, {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, sock_str_flag},#ifdefSO_REUSEPORT{"SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT, sock_str_flag},#else{"SO_REUSEPORT", 0, 0, NULL},#endif{"SO_TYPE", SOL_SOCKET, SO_TYPE, sock_str_int},    /*              { "SO_USELOOPBACK", SOL_SOCKET, SO_USELOOPBACK, sock_str_flag }, */{"IP_TOS", IPPROTO_IP, IP_TOS, sock_str_int}, {"IP_TTL", IPPROTO_IP, IP_TTL, sock_str_int},#ifdef IPV6#ifdefIPV6_DONTFRAG{"IPV6_DONTFRAG", IPPROTO_IPV6, IPV6_DONTFRAG, sock_str_flag},#else{"IPV6_DONTFRAG", 0, 0, NULL},#endif#ifdefIPV6_UNICAST_HOPS{"IPV6_UNICAST_HOPS", IPPROTO_IPV6, IPV6_UNICAST_HOPS,    sock_str_int},#else{"IPV6_UNICAST_HOPS", 0, 0, NULL},#endif#ifdefIPV6_V6ONLY{"IPV6_V6ONLY", IPPROTO_IPV6, IPV6_V6ONLY, sock_str_flag},#else{"IPV6_V6ONLY", 0, 0, NULL},#endif#endif{"TCP_MAXSEG", IPPROTO_TCP, TCP_MAXSEG, sock_str_int}, {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, sock_str_flag},#ifdefSCTP_AUTOCLOSE{"SCTP_AUTOCLOSE", IPPROTO_SCTP, SCTP_AUTOCLOSE, sock_str_int},#else{"SCTP_AUTOCLOSE", 0, 0, NULL},#endif#ifdefSCTP_MAXBURST{"SCTP_MAXBURST", IPPROTO_SCTP, SCTP_MAXBURST, sock_str_int},#else{"SCTP_MAXBURST", 0, 0, NULL},#endif#ifdefSCTP_MAXSEG{"SCTP_MAXSEG", IPPROTO_SCTP, SCTP_MAXSEG, sock_str_int},#else{"SCTP_MAXSEG", 0, 0, NULL},#endif#ifdefSCTP_NODELAY{"SCTP_NODELAY", IPPROTO_SCTP, SCTP_NODELAY, sock_str_flag},#else{"SCTP_NODELAY", 0, 0, NULL},#endif{NULL, 0, 0, NULL}};/* *INDENT-ON* */void err_doit(int errnoflag, int level, const char *fmt, va_list ap){int errno_save, n;char buf[MAXLINE + 1];errno_save = errno;/* value caller might want printed */#ifdefHAVE_VSNPRINTFvsnprintf(buf, MAXLINE, fmt, ap);/* safe */#elsevsprintf(buf, fmt, ap);/* not safe */#endifn = strlen(buf);if (errnoflag)snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save));strcat(buf, "\n");if (daemon_proc) {syslog(level, "%s", buf);} else {fflush(stdout);/* in case stdout and stderr are the same */fputs(buf, stderr);fflush(stderr);}return;}void err_quit(const char *fmt, ...){va_list ap;va_start(ap, fmt);err_doit(0, LOG_ERR, fmt, ap);va_end(ap);exit(1);}void err_sys(const char *fmt, ...){va_list ap;va_start(ap, fmt);err_doit(1, LOG_ERR, fmt, ap);va_end(ap);exit(1);}void err_ret(const char *fmt, ...){va_list ap;va_start(ap, fmt);err_doit(1, LOG_INFO, fmt, ap);va_end(ap);return;}int Socket(int family, int type, int protocol){int n;if ((n = socket(family, type, protocol)) < 0)err_sys("socket error");return (n);}int main(){int fd;socklen_t len;struct sock_opts *ptr;for (ptr = sock_opts; ptr->opt_str != NULL; ptr++) {printf("%s: ", ptr->opt_str);if (ptr->opt_val_str == NULL)printf("(undefined)\n");else {switch (ptr->opt_level) {case SOL_SOCKET:case IPPROTO_IP:case IPPROTO_TCP:fd = Socket(AF_INET, SOCK_STREAM, 0);break;#ifdefIPV6case IPPROTO_IPV6:fd = Socket(AF_INET6, SOCK_STREAM, 0);break;#endif#ifdefIPPROTO_SCTPcase IPPROTO_SCTP:fd = Socket(AF_INET, SOCK_SEQPACKET,    IPPROTO_SCTP);break;#endifdefault:err_quit("Can't create fd for level %d\n", ptr->opt_level);}len = sizeof(val);if (getsockopt    (fd, ptr->opt_level, ptr->opt_name, &val,     &len) == -1) {err_ret("getsockopt error");} else {printf("default = %s\n",       (*ptr->opt_val_str) (&val, len));}close(fd);}}exit(0);}

原创粉丝点击