这两个函数仅用于套接字。
函数原型:
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,结果截图: