LINUX下getsockopt和setsockopt函数

这两个函数仅用于套接字。

函数原型:

1 #include <sys/socket.h>
2 #include <sys/types.h>
3 
4 int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);
5 
6 int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

sockfd:必须指向一个打开的套接字描述符

level:指定系统中解释选项的代码或为通用套接字代码,或为某个特定于协议的代码(例如IPv4、IPv6、TCP或SCTP)。

optval:指向某个变量(*optval)的指针,setsockopt从*optval中取得选项设置的新值,getsockopt则把以获取的选项当前值存入*optval。

optlen:指定*optval的大小

套接字选项的汇总可以查看unix网络编程(卷1)151页 图7-1和图7-2.

并非所有实现都支持所有的套接字选项,下面的程序可以简单测试系统是否支持选项:

  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 #ifdef  SO_BROADCAST
 25     { "SO_BROADCAST",        SOL_SOCKET,    SO_BROADCAST,    sock_str_flag },
 26 #else
 27     { "SO_BROADCAST",            0,        0,        NULL},
 28 #endif
 29 #ifdef  SO_DEBUG
 30     { "SO_DEBUG",            SOL_SOCKET,    SO_DEBUG,        sock_str_flag },
 31 #else
 32     { "SO_DEBUG",                0,        0,        NULL},
 33 #endif
 34 #ifdef  SO_DONTROUTE
 35     { "SO_DONTROUTE",        SOL_SOCKET,    SO_DONTROUTE,    sock_str_flag },
 36 #else
 37     { "SO_DONTROUTE",            0,        0,        NULL},
 38 #endif
 39 #ifdef  SO_ERROR
 40     { "SO_ERROR",            SOL_SOCKET,    SO_ERROR,        sock_str_int },
 41 #else
 42     { "SO_ERROR",                0,        0,        NULL},
 43 #endif
 44 #ifdef  SO_KEEPALIVE
 45     { "SO_KEEPALIVE",        SOL_SOCKET,    SO_KEEPALIVE,    sock_str_flag },
 46 #else
 47     { "SO_KEEPALIVE",            0,        0,        NULL},
 48 #endif
 49 #ifdef  SO_LINGER
 50     { "SO_LINGER",            SOL_SOCKET,    SO_LINGER,        sock_str_linger },
 51 #else
 52     { "SO_LINGER",                0,        0,        NULL},
 53 #endif
 54 #ifdef  SO_OOBINLINE
 55     { "SO_OOBINLINE",        SOL_SOCKET,    SO_OOBINLINE,    sock_str_flag },
 56 #else
 57     : "SO_OOBINLINE",            0,        0,        NULL},
 58 #endif
 59 #ifdef  SO_RCVBUF
 60     { "SO_RCVBUF",            SOL_SOCKET,    SO_RCVBUF,        sock_str_int },
 61 #else
 62     { "SO_RCVBUF",                0,        0,        NULL},
 63 #endif
 64 #ifdef  SO_SNDBUF
 65     { "SO_SNDBUF",            SOL_SOCKET,    SO_SNDBUF,        sock_str_int },
 66 #else
 67     { "SO_SNDBUF",                0,        0,        NULL},
 68 #endif
 69 #ifdef  SO_RCVLOWAT
 70     { "SO_RCVLOWAT",        SOL_SOCKET,    SO_RCVLOWAT,    sock_str_int },
 71 #else
 72     { "SO_RCVLOWAT",            0,        0,        NULL},
 73 #endif
 74 #ifdef  SO_SNDLOWAT
 75     { "SO_SNDLOWAT",        SOL_SOCKET,    SO_SNDLOWAT,    sock_str_int },
 76 #else
 77     { "SO_SNDLOWAT",            0,        0,        NULL},
 78 #endif
 79 #ifdef  SO_RCVTIMEO
 80     { "SO_RCVTIMEO",        SOL_SOCKET,    SO_RCVTIMEO,    sock_str_timeval },
 81 #else
 82     { "SO_RCVTIMEO",            0,        0,        NULL},
 83 #endif
 84 #ifdef  SO_SNDTIMEO
 85     { "SO_SNDTIMEO",        SOL_SOCKET,    SO_SNDTIMEO,    sock_str_timeval },
 86 #else
 87     { "SO_SNDTIMEO",            0,        0,        NULL},
 88 #endif
 89 #ifdef  SO_REUSEADDR
 90     { "SO_REUSEADDR",        SOL_SOCKET,    SO_REUSEADDR,    sock_str_flag },
 91 #else
 92     { "SO_REUSEADDR",            0,        0,        NULL},
 93 #endif
 94 #ifdef    SO_REUSEPORT
 95     { "SO_REUSEPORT",        SOL_SOCKET,    SO_REUSEPORT,    sock_str_flag },
 96 #else
 97     { "SO_REUSEPORT",        0,            0,                NULL },
 98 #endif
 99 #ifdef  SO_TYPE
100     { "SO_TYPE",            SOL_SOCKET,    SO_TYPE,        sock_str_int },
101 #else
102     { "SO_TYPE",            0,            0,        NULL},
103 #endif
104 #ifdef  SO_USELOOPBACK
105     { "SO_USELOOPBACK",        SOL_SOCKET,    SO_USELOOPBACK,    sock_str_flag },
106 #else
107     { "SO_USELOOPBACK",        0,            0,                NULL},
108 #endif
109 #ifdef  IP_TOS
110     { "IP_TOS",                IPPROTO_IP,    IP_TOS,            sock_str_int },
111 #else
112     { "IP_TOS",            0,            0,        NULL},
113 #endif
114 #ifdef  IP_TTL
115     { "IP_TTL",                IPPROTO_IP,    IP_TTL,            sock_str_int },
116 #else
117     { "IP_TTL",            0,            0,        NULL},
118 #endif
119 #ifdef    IPV6_DONTFRAG
120     { "IPV6_DONTFRAG",        IPPROTO_IPV6,IPV6_DONTFRAG,    sock_str_flag },
121 #else
122     { "IPV6_DONTFRAG",        0,            0,                NULL },
123 #endif
124 #ifdef    IPV6_UNICAST_HOPS
125     { "IPV6_UNICAST_HOPS",    IPPROTO_IPV6,IPV6_UNICAST_HOPS,sock_str_int },
126 #else
127     { "IPV6_UNICAST_HOPS",    0,            0,                NULL },
128 #endif
129 #ifdef    IPV6_V6ONLY
130     { "IPV6_V6ONLY",        IPPROTO_IPV6,IPV6_V6ONLY,    sock_str_flag },
131 #else
132     { "IPV6_V6ONLY",        0,            0,                NULL },
133 #endif
134 #ifdef  TCP_MAXSEG
135     { "TCP_MAXSEG",            IPPROTO_TCP,TCP_MAXSEG,        sock_str_int },
136 #else
137     { "TCP_MAXSEG",            0,            0,            NULL},
138 #endif
139 #ifdef  TCP_NODELAY
140     { "TCP_NODELAY",        IPPROTO_TCP,TCP_NODELAY,    sock_str_flag },
141 #else
142     { "TCP_NODELAY",        0,            0,            NULL},
143 #endif
144 #ifdef    SCTP_AUTOCLOSE
145     { "SCTP_AUTOCLOSE",        IPPROTO_SCTP,SCTP_AUTOCLOSE,sock_str_int },
146 #else
147     { "SCTP_AUTOCLOSE",        0,            0,                NULL },
148 #endif
149 #ifdef    SCTP_MAXBURST
150     { "SCTP_MAXBURST",        IPPROTO_SCTP,SCTP_MAXBURST,    sock_str_int },
151 #else
152     { "SCTP_MAXBURST",        0,            0,                NULL },
153 #endif
154 #ifdef    SCTP_MAXSEG
155     { "SCTP_MAXSEG",        IPPROTO_SCTP,SCTP_MAXSEG,    sock_str_int },
156 #else
157     { "SCTP_MAXSEG",        0,            0,                NULL },
158 #endif
159 #ifdef    SCTP_NODELAY
160     { "SCTP_NODELAY",        IPPROTO_SCTP,SCTP_NODELAY,    sock_str_flag },
161 #else
162     { "SCTP_NODELAY",        0,            0,                NULL },
163 #endif
164     { NULL,                    0,            0,                NULL }
165 };
166 /* *INDENT-ON* */
167 /* end checkopts1 */
168 
169 /* include checkopts2 */
170 int
171 main(int argc, char **argv)
172 {
173     int                    fd;
174     socklen_t            len;
175     struct sock_opts    *ptr;
176 
177     for (ptr = sock_opts; ptr->opt_str != NULL; ptr++) {
178         printf("%s: ", ptr->opt_str);
179         if (ptr->opt_val_str == NULL)
180             printf("(undefined)
");
181         else {
182             switch(ptr->opt_level) {
183             case SOL_SOCKET:
184             case IPPROTO_IP:
185             case IPPROTO_TCP:
186                 fd = Socket(AF_INET, SOCK_STREAM, 0);
187                 break;
188 #ifdef    IPV6
189             case IPPROTO_IPV6:
190                 fd = Socket(AF_INET6, SOCK_STREAM, 0);
191                 break;
192 #endif
193 #ifdef    IPPROTO_SCTP
194             case IPPROTO_SCTP:
195                 fd = Socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
196                 break;
197 #endif
198             default:
199                 err_quit("Can't create fd for level %d
", ptr->opt_level);
200             }
201 
202             len = sizeof(val);
203             if (getsockopt(fd, ptr->opt_level, ptr->opt_name,
204                            &val, &len) == -1) {
205                 err_ret("getsockopt error");
206             } else {
207                 printf("default = %s
", (*ptr->opt_val_str)(&val, len));
208             }
209             close(fd);
210         }
211     }
212     exit(0);
213 }
214 /* end checkopts2 */
215 
216 /* include checkopts3 */
217 static char    strres[128];
218 
219 static char    *
220 sock_str_flag(union val *ptr, int len)
221 {
222 /* *INDENT-OFF* */
223     if (len != sizeof(int))
224         snprintf(strres, sizeof(strres), "size (%d) not sizeof(int)", len);
225     else
226         snprintf(strres, sizeof(strres),
227                  "%s", (ptr->i_val == 0) ? "off" : "on");
228     return(strres);
229 /* *INDENT-ON* */
230 }
231 /* end checkopts3 */
232 
233 static char    *
234 sock_str_int(union val *ptr, int len)
235 {
236     if (len != sizeof(int))
237         snprintf(strres, sizeof(strres), "size (%d) not sizeof(int)", len);
238     else
239         snprintf(strres, sizeof(strres), "%d", ptr->i_val);
240     return(strres);
241 }
242 
243 static char    *
244 sock_str_linger(union val *ptr, int len)
245 {
246     struct linger    *lptr = &ptr->linger_val;
247 
248     if (len != sizeof(struct linger))
249         snprintf(strres, sizeof(strres),
250                  "size (%d) not sizeof(struct linger)", len);
251     else
252         snprintf(strres, sizeof(strres), "l_onoff = %d, l_linger = %d",
253                  lptr->l_onoff, lptr->l_linger);
254     return(strres);
255 }
256 
257 static char    *
258 sock_str_timeval(union val *ptr, int len)
259 {
260     struct timeval    *tvptr = &ptr->timeval_val;
261 
262     if (len != sizeof(struct timeval))
263         snprintf(strres, sizeof(strres),
264                  "size (%d) not sizeof(struct timeval)", len);
265     else
266         snprintf(strres, sizeof(strres), "%ld sec, %ld usec",
267                  tvptr->tv_sec, tvptr->tv_usec);
268     return(strres);
269 }

我用的系统是Ubuntu 13.04,结果截图:

原文地址:https://www.cnblogs.com/xianzhedeyu/p/3298649.html