套接字选项是否从侦听套接字继承到accept()?

R..*_*R.. 27 c sockets posix

假设传递给的侦听套接字上accept设置了非默认选项setsockopt.这些选项(部分或全部?)是由接收连接的结果文件描述符继承的吗?

ask*_*ish 9

一些套接字选项在系统的较低级别处理.虽然可以使用setsockopt设置大多数套接字选项.参考:man setsockopt并且因为你在任何Linux上都只提到POSIX,一般来说,作为你的范围.的accept()(参考:man accept)确实有一定量的什么套接字选项应该被继承判断和哪些选择从听音FD拒绝.

accept()不会修改作为参数传递给它的原始套接字.accept()返回的新套接字不会从侦听套接字继承文件状态标志,如O_NONBLOCK,O_ASYNC.

因此,不应依赖于侦听套接字属性的继承或非继承(它必须在实现和许可证之间变化),应使用所需的套接字选项显式设置接受的套接字.(最佳实践)

手册页中的手册页和实现代码将是accept()行为最相关的规范.在Linux的多个变体中没有共同的或标准的规范.


Ada*_*eld 5

不,它们不一定是遗传的。试试这个示例,它将SO_RCVBUF初始套接字上的接收缓冲区大小 ( ) 设置为非默认值,然后将结果与继承的套接字进行比较。运行此代码,它侦听 TCP 端口 12345,然后从任何其他程序连接到它。

#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>

void die(const char *f)
{
  printf("%s: %s\n", f, strerror(errno));
  exit(1);
}

int main(void)
{
  int s = socket(AF_INET, SOCK_STREAM, 0);
  if(s < 0)
    die("socket");

  int rcvbuf;
  socklen_t optlen = sizeof(rcvbuf);
  if(getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &optlen) < 0)
    die("getsockopt (1)");
  printf("initial rcvbuf: %d\n", rcvbuf);
  rcvbuf *= 2;
  if(setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) < 0)
    die("setsockopt");
  printf("set rcvbuf to %d\n", rcvbuf);

  struct sockaddr_in sin;
  memset(&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_port = htons(12345);
  sin.sin_addr.s_addr = INADDR_ANY;
  if(bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
    die("bind");

  if(listen(s, 10) < 0)
    die("listen");

  struct sockaddr_in client_addr;
  socklen_t addr_len = sizeof(client_addr);
  int s2 = accept(s, (struct sockaddr *)&client_addr, &addr_len);
  if(s2 < 0)
    die("accept");
  printf("accepted connection\n");
  optlen = sizeof(rcvbuf);
  if(getsockopt(s2, SOL_SOCKET, SO_RCVBUF, &rcvbuf, &optlen) < 0)
    die("getsockopt (2)");

  printf("new rcvbuf: %d\n", rcvbuf);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

在运行 Linux 3.0.0-21-generic 的机器上的结果:

initial rcvbuf: 87380
set rcvbuf to 174760
accepted connection
new rcvbuf: 262142
Run Code Online (Sandbox Code Playgroud)

  • 我不认为是这种情况(但我可能是错的,这里是参考)。"SO_RCVBUF 以字节为单位设置或获取最大套接字接收缓冲区。内核在使用setsockopt(2) 设置时将该值加倍(以允许簿记开销的空间),并且该加倍值由getsockopt(2) 返回。默认值值由 /proc/sys/net/core/rmem_default 文件设置,允许的最大值由 /proc/sys/net/core/rmem_max 文件设置。此选项的最小(双倍)值为 256" . http://linux.die.net/man/7/socket。 (2认同)

M. *_*ast 2

据我了解,对于符合 POSIX 的实现,答案是否定的。

来自accept()的POSIX-2017规范:

accept() 函数应提取挂起连接队列中的第一个连接,创建一个与指定套接字具有相同套接字类型协议和地址族的新套接字,并为该套接字分配一个新的文件描述符。

请注意,它明确是一个“新套接字”,而不是“未排队的套接字的完整或部分副本”,因此不应有与该套接字类型和地址族的默认值不同的选项。虽然复制行为可能是理想的,但这被保留为平台可能具有的扩展接口。然而,我还没有看到任何平台确实实现了这一功能,因此可以将其添加到标准中。因此,在使用该套接字发送之前,应用程序应使用 getsockopt()/setsockopt() 将与默认值不同的任何属性从队列套接字复制到返回的套接字,而不是接口的责任或接收数据。