概述
linux下getsockopt和setsockopt详解及测试
NAME
名字
getsockopt, setsockopt - get and set options on sockets
获取或者设置套接字的选项
SYNOPSIS
函数原型
#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);
参数:
sock:将要被设置或者获取选项的套接字。
level:选项所在的协议层。
optname:需要访问的选项名。
optval:对于getsockopt(),指向返回选项值的缓冲。
对于setsockopt(),指向包含新选项值的缓冲。
optlen:对于getsockopt(),作为入口参数时,选项值的最大长度。作为出口参数时,选项值的实际长度。
对于setsockopt(),The size, in bytes, of the optval buffer.
level指定控制套接字的层次.可以取三种值:
1)SOL_SOCKET:通用套接字选项.
2)IPPROTO_IP:IP选项.
3)IPPROTO_TCP:TCP选项.
RETURN VALUE
返回值
On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
错误返回
ERRORS
EBADF
The argument sockfd is not a valid descriptor.
EFAULT
The
address
pointed
to
by optval is not in a valid part of the process address space.
For getsockopt(), this error may
also be returned if optlen is not in a valid part of the process address space.//
EINVAL
optlen invalid in setsockopt().
In some cases this error can also occur for an invalid value
in
optval
(e.g.,
for
the
IP_ADD_MEMBERSHIP option described in ip(7)).
ENOPROTOOPT
The option is unknown at the level indicated.
ENOTSOCK
The argument sockfd is a file, not a socket.
EBADF:sock不是有效的文件描述词
EFAULT:optval指向的内存并非有效的进程空间
EINVAL:在调用setsockopt()时,optlen无效
ENOPROTOOPT:指定的协议层不能识别选项
ENOTSOCK:sock描述的不是套接字
套接字选项和IP层的套接字选项汇总见《unix网络编程第三版卷一》P151图7-1
下面用一段小代码来检查选项是否受支持并获取默认值:
root@wl-Lenovo-B590:/myworkspace/unixnetwork/unpv13e/sockopt# cat -n checkopts.c
1 /* include checkopts1 */
2 /* *INDENT-OFF* */
3 #include "unp.h"
4 #include <netinet/tcp.h>
/* for TCP_xxx defines */
5
6 union val {
7
int
i_val;
8
long
l_val;
9
struct linger
linger_val;
10
struct timeval timeval_val;
11 } val;
12
13 static char *sock_str_flag(union val *, int);
14 static char *sock_str_int(union val *, int);
15 static char *sock_str_linger(union val *, int);
16 static char *sock_str_timeval(union val *, int);
17
18 struct sock_opts {
19
const char
*opt_str;
20
int
opt_level;
21
int
opt_name;
22
char
*(*opt_val_str)(union val *, int);
23 } sock_opts[] = {
24
{ "SO_BROADCAST",
SOL_SOCKET, SO_BROADCAST, sock_str_flag },
25
{ "SO_DEBUG",
SOL_SOCKET, SO_DEBUG,
sock_str_flag },
26
{ "SO_DONTROUTE",
SOL_SOCKET, SO_DONTROUTE, sock_str_flag },
27
{ "SO_ERROR",
SOL_SOCKET, SO_ERROR,
sock_str_int },
28
{ "SO_KEEPALIVE",
SOL_SOCKET, SO_KEEPALIVE, sock_str_flag },
29
{ "SO_LINGER",
SOL_SOCKET, SO_LINGER,
sock_str_linger },
30
{ "SO_OOBINLINE",
SOL_SOCKET, SO_OOBINLINE, sock_str_flag },
31
{ "SO_RCVBUF",
SOL_SOCKET, SO_RCVBUF,
sock_str_int },
32
{ "SO_SNDBUF",
SOL_SOCKET, SO_SNDBUF,
sock_str_int },
33
{ "SO_RCVLOWAT",
SOL_SOCKET, SO_RCVLOWAT, sock_str_int },
34
{ "SO_SNDLOWAT",
SOL_SOCKET, SO_SNDLOWAT, sock_str_int },
35
{ "SO_RCVTIMEO",
SOL_SOCKET, SO_RCVTIMEO, sock_str_timeval },
36
{ "SO_SNDTIMEO",
SOL_SOCKET, SO_SNDTIMEO, sock_str_timeval },
37
{ "SO_REUSEADDR",
SOL_SOCKET, SO_REUSEADDR, sock_str_flag },
38 #ifdef SO_REUSEPORT
39
{ "SO_REUSEPORT",
SOL_SOCKET, SO_REUSEPORT, sock_str_flag },
40 #else
41
{ "SO_REUSEPORT",
0,
0,
NULL },
42 #endif
43
{ "SO_TYPE",
SOL_SOCKET, SO_TYPE,
sock_str_int },
44 // { "SO_USELOOPBACK",
SOL_SOCKET, SO_USELOOPBACK, sock_str_flag },
45
{ "IP_TOS",
IPPROTO_IP, IP_TOS,
sock_str_int },
46
{ "IP_TTL",
IPPROTO_IP, IP_TTL,
sock_str_int },
47 #ifdef IPV6_DONTFRAG
48
{ "IPV6_DONTFRAG",
IPPROTO_IPV6,IPV6_DONTFRAG, sock_str_flag },
49 #else
50
{ "IPV6_DONTFRAG",
0,
0,
NULL },
51 #endif
52 #ifdef IPV6_UNICAST_HOPS
53
{ "IPV6_UNICAST_HOPS", IPPROTO_IPV6,IPV6_UNICAST_HOPS,sock_str_int },
54 #else
55
{ "IPV6_UNICAST_HOPS", 0,
0,
NULL },
56 #endif
57 #ifdef IPV6_V6ONLY
58
{ "IPV6_V6ONLY",
IPPROTO_IPV6,IPV6_V6ONLY, sock_str_flag },
59 #else
60
{ "IPV6_V6ONLY",
0,
0,
NULL },
61 #endif
62
{ "TCP_MAXSEG",
IPPROTO_TCP,TCP_MAXSEG,
sock_str_int },
63
{ "TCP_NODELAY",
IPPROTO_TCP,TCP_NODELAY, sock_str_flag },
64 #ifdef SCTP_AUTOCLOSE
65
{ "SCTP_AUTOCLOSE",
IPPROTO_SCTP,SCTP_AUTOCLOSE,sock_str_int },
66 #else
67
{ "SCTP_AUTOCLOSE",
0,
0,
NULL },
68 #endif
69 #ifdef SCTP_MAXBURST
70
{ "SCTP_MAXBURST",
IPPROTO_SCTP,SCTP_MAXBURST, sock_str_int },
71 #else
72
{ "SCTP_MAXBURST",
0,
0,
NULL },
73 #endif
74 #ifdef SCTP_MAXSEG
75
{ "SCTP_MAXSEG",
IPPROTO_SCTP,SCTP_MAXSEG, sock_str_int },
76 #else
77
{ "SCTP_MAXSEG",
0,
0,
NULL },
78 #endif
79 #ifdef SCTP_NODELAY
80
{ "SCTP_NODELAY",
IPPROTO_SCTP,SCTP_NODELAY, sock_str_flag },
81 #else
82
{ "SCTP_NODELAY",
0,
0,
NULL },
83 #endif
84
{ NULL,
0,
0,
NULL }
85 };
86 /* *INDENT-ON* */
87 /* end checkopts1 */
88
89 /* include checkopts2 */
90 int
91 main(int argc, char **argv)
92 {
93
int
fd;
94
socklen_t
len;
95
struct sock_opts *ptr;
96
97
for (ptr = sock_opts; ptr->opt_str != NULL; ptr++) {
98
printf("%s: ", ptr->opt_str);
99
if (ptr->opt_val_str == NULL)
100
printf("(undefined)n");
101
else {
102
switch(ptr->opt_level) {
103
case SOL_SOCKET:
104
case IPPROTO_IP:
105
case IPPROTO_TCP:
106
fd = Socket(AF_INET, SOCK_STREAM, 0);
107
break;
108 #ifdef IPV6
109
case IPPROTO_IPV6:
110
fd = Socket(AF_INET6, SOCK_STREAM, 0);
111
break;
112 #endif
113 #ifdef IPPROTO_SCTP
114
case IPPROTO_SCTP:
115
fd = Socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
116
break;
117 #endif
118
default:
119
err_quit("Can't create fd for level %dn", ptr->opt_level);
120
}
121
122
len = sizeof(val);
123
if (getsockopt(fd, ptr->opt_level, ptr->opt_name,
124
&val, &len) == -1) {
125
err_ret("getsockopt error");
126
} else {
127
printf("default = %sn", (*ptr->opt_val_str)(&val, len));
128
}
129
close(fd);
130
}
131
}
132
exit(0);
133 }
134 /* end checkopts2 */
135
136 /* include checkopts3 */
137 static char strres[128];
138
139 static char *
140 sock_str_flag(union val *ptr, int len)
141 {
142 /* *INDENT-OFF* */
143
if (len != sizeof(int))
144
snprintf(strres, sizeof(strres), "size (%d) not sizeof(int)", len);
145
else
146
snprintf(strres, sizeof(strres),
147
"%s", (ptr->i_val == 0) ? "off" : "on");
148
return(strres);
149 /* *INDENT-ON* */
150 }
151 /* end checkopts3 */
152
153 static char *
154 sock_str_int(union val *ptr, int len)
155 {
156
if (len != sizeof(int))
157
snprintf(strres, sizeof(strres), "size (%d) not sizeof(int)", len);
158
else
159
snprintf(strres, sizeof(strres), "%d", ptr->i_val);
160
return(strres);
161 }
162
163 static char *
164 sock_str_linger(union val *ptr, int len)
165 {
166
struct linger *lptr = &ptr->linger_val;
167
168
if (len != sizeof(struct linger))
169
snprintf(strres, sizeof(strres),
170
"size (%d) not sizeof(struct linger)", len);
171
else
172
snprintf(strres, sizeof(strres), "l_onoff = %d, l_linger = %d",
173
lptr->l_onoff, lptr->l_linger);
174
return(strres);
175 }
176
177 static char *
178 sock_str_timeval(union val *ptr, int len)
179 {
180
struct timeval *tvptr = &ptr->timeval_val;
181
182
if (len != sizeof(struct timeval))
183
snprintf(strres, sizeof(strres),
184
"size (%d) not sizeof(struct timeval)", len);
185
else
186
snprintf(strres, sizeof(strres), "%d sec, %d usec",
187
tvptr->tv_sec, tvptr->tv_usec);
188
return(strres);
189 }
root@wl-Lenovo-B590:/myworkspace/unixnetwork/unpv13e/sockopt# man getsockopt
测试运行结果如图:
参考:UNIX网络编程卷一
Linux Programmer's Manual
最后
以上就是专一金针菇为你收集整理的linux下getsockopt和setsockopt详解及测试linux下getsockopt和setsockopt详解及测试 的全部内容,希望文章能够帮你解决linux下getsockopt和setsockopt详解及测试linux下getsockopt和setsockopt详解及测试 所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复