一、getsockopt/setsockopt 函数
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int getsockopt(int sockfd, int level, int optname,
void *optval, socklen_t *optlen);
int setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen);
sockfd:已打开的socket描述符
level:级别
optval:指向某个变量的指针,若是setsockopt,则为要设置的新值,若是getsockopt则为获取到选项的值存到该变量中
optlen:optval的长度
二,套接字选项
三、获取默认设置程序示例
/*getsockopt.c*/
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <string.h>
union val
{
int i_val;
int l_val;
struct linger linger_val;
struct timeval timeval_val;
}val;
static char *sock_str_flag(union val *, int);
static char *sock_str_int(union val *, int);
static char *sock_str_linger(union val *, int);
static char *sock_str_timeval(union val *, int);
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},
#ifdef SO_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},
//{"IPV6_DONTFRAG",IPPROTO_IPV6, IPV6_DONTFRAG,sock_str_flag},
//{"IPV6_UNICAST_HOPS",IPPROTO_IPV6,IPV6_UNICAST_HOPS,sock_str_int},
//{"IPV6_V6ONLY", IPPROTO_IPV6, IPV6_V6ONLY, sock_str_flag},
{"TCP_MAXSEG", IPPROTO_TCP, TCP_MAXSEG, sock_str_int},
{"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, sock_str_flag},
//{"SCTP_AUTOCLOSE",IPPROTO_SCTP, SCTP_AUTOCLOSE, sock_str_int},
//{"SCTP_MAXBURST", IPPROTO_SCTP, SCTP_MAXBURST, sock_str_int},
//{"SCTP_MAXSEG", IPPROTO_SCTP, SCTP_MAXSEG, sock_str_int},
//{"SCTP_NODELAY", IPPROTO_SCTP, SCTP_NODELAY, sock_str_flag},
{NULL, 0, 0, NULL}
};
static char str[128];
static char *sock_str_flag(union val *ptr, int len)
{
bzero(str, sizeof(str));
if (len != sizeof(int))
snprintf(str, sizeof(str), "size (%d) not sizeof(int)", len);
else
snprintf(str, sizeof(str), "status: %s", (ptr->i_val==0) ? "off" : "on");
return str;
}
static char *sock_str_int(union val *ptr, int len)
{
bzero(str, sizeof(str));
if (len != sizeof(int))
snprintf(str, sizeof(str), "size (%d) not sizeof(int)", len);
else
snprintf(str, sizeof(str), "val: %d", ptr->l_val);
return str;
}
static char *sock_str_linger(union val *ptr, int len)
{
bzero(str, sizeof(str));
if (len != sizeof(struct linger))
snprintf(str, sizeof(str), "size (%d) not sizeof(int)", len);
else
snprintf(str, sizeof(str), "l_onoff: %d, l_linger: %d", ptr->linger_val.l_onoff, ptr->linger_val.l_linger);
return str;
}
static char *sock_str_timeval(union val *ptr, int len)
{
bzero(str, sizeof(str));
if (len != sizeof(struct timeval))
snprintf(str, sizeof(str), "size (%d) not sizeof(int)", len);
else
snprintf(str, sizeof(str), "sec: %ld, usec: %ld", ptr->timeval_val.tv_sec, ptr->timeval_val.tv_usec);
return str;
}
int main(void)
{
socklen_t len;
int fd;
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("Undefine.\n");
}else
{
switch(ptr->opt_level)
{
case SOL_SOCKET:
case IPPROTO_IP:
case IPPROTO_TCP:
fd = socket(AF_INET, SOCK_STREAM, 0);
break;
#ifdef IPV6
case IPPROTO_IPV6
fd = socket(AF_INET6, SOCK_STREAM, 0);
break;
#endif
#ifdef IPPROTO_SCTP
case IPPROTO_SCTP:
fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
break;
#endif
default:
printf("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)
{
printf("getsockopt failed.\n");
exit(1);
}else
{
printf("%s\n", (*ptr->opt_val_str)(&val, len));
}
close(fd);
}
}
return 0;
}