SO_REUSEADDR似乎持有值4。

3

我一直在尝试学习使用c进行套接字编程,但我遇到了一些困惑的事情。我写了这段代码:

int main(int argc, char *argv[]) {
      int sockfd = socket(AF_INET, SOCK_STREAM, 0);
      int opt = 1;

      if(sockfd == -1) {
              printf("socket error\n");
              exit(EXIT_FAILURE);
      }

      if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
              printf("setsockopt error\n");
              exit(EXIT_FAILURE);
      }

      int getOpt;
      socklen_t  getOptLen = sizeof(getOpt);
      getsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &getOpt, &getOptLen);

      printf("%d\n", getOpt);
 }

我原本期望它会打印出1,因为这是我传给setsockopt的值,但是它却打印出了4。SO_REUSEADDR的布尔值被存储为4吗?我是否错误地使用了getsockopt?


这些调用可以设置一堆选项为true/false。恰好,SO_REUSEADDR的SOL-SOCKET值为00000100B,因此打开它会将选项值设置为4。 - Martin James
@MartinJames 我不明白。00000100B和4之间没有联系,SO_REUSEADDR的值和某个选项字中设置的位也没有关系。 - user207421
@EJP请参见下面的sg7答案。这些opt只是选项值的位掩码OR在一起。4作为二进制字节是00000100,虽然它可能是一个无符号整数,但我已经厌倦了数0的个数。 - Martin James
2个回答

2

SO_REUSEADDR 的值为 4。或者用十六进制表示为 (0x0004)

#define SO_REUSEADDR    0x0004      /* allow local address reuse */

查看其他选项的定义:

/*
 * Option flags per-socket.
 */
#define SO_DEBUG        0x0001      /* turn on debugging info recording */
#define SO_ACCEPTCONN   0x0002      /* socket has had listen() */
#define SO_REUSEADDR    0x0004      /* allow local address reuse */
#define SO_KEEPALIVE    0x0008      /* keep connections alive */
#define SO_DONTROUTE    0x0010      /* just use interface addresses */
#define SO_BROADCAST    0x0020      /* permit sending of broadcast msgs */
#define SO_USELOOPBACK  0x0040      /* bypass hardware when possible */
#define SO_LINGER       0x0080      /* linger on close if data present */
#define SO_OOBINLINE    0x0100      /* leave received OOB data in line */

你可能想看一下这个:socket.h 头文件。

1
这并没有直接回答问题。 - John Zwinck
谢谢,我会查一下socket.h文件。 - Eric Oseid
socket.h 的链接已失效。 - hasen
1
@hasen 感谢您的评论!我已经添加了来自OpenBSD的socket.h新链接。 - sg7

1
SO_REUSEADDR的值是一个布尔值。在C语言中,布尔值有多个位,如果任何一个位被设置,它就被认为是真。也就是说,0表示假,而其他任何值都表示真。
得到数字4可能有点奇怪,但这只是实现的一种怪癖。你的代码没有问题。除了检查它是否为零或非零之外,你不应该使用getOpt的数值。
猜测:实现可能会将几个布尔套接字选项存储在单个整数中,并映射以表明SO_REUSEADDR是第2位(如果设置,则其值为4)。

1
@spinkus:我详尽地枚举了可能的错误返回代码以及每个代码在给定 OP 的代码情况下为何不会发生。我同意无论如何检查返回值都是一个好主意。请注意,OP 的代码实际上并没有连接到任何东西,因此不存在网络故障对套接字造成影响的可能性(例如)。 - John Zwinck
1
@spinkus 在成功的setsockopt()之后,它不会立即变为无效。它需要一个中间的close()。这些"一串英文单词"指的是它们所记录的具体实现方式。 - user207421
@JohnZwinck 把选项放在一个整数中有什么好处? 它更省空间吗? - Eric Oseid
@spinkus 抱歉,我没有意识到我没有进行错误检查。函数为什么在成功时返回0而在完成时返回-1?如果它在成功时返回1而在失败时返回0,那么我的代码就是有效的。 - Eric Oseid
@EricOseid:是的,当然,如果有一组标志,使用每个标志位一个比特比使用每个字节或单词更节省空间。 - John Zwinck
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接