Параметры сокета наследуются через accept () от слушающего сокета? - PullRequest
27 голосов
/ 11 мая 2011

Предположим, что для сокета прослушивания, переданного в accept, установлены нестандартные параметры с setsockopt. Являются ли эти параметры (некоторые или все?) Унаследованными результирующими файловыми дескрипторами для принятых соединений?

Ответы [ 4 ]

9 голосов
/ 12 октября 2012

Некоторые опции сокетов обрабатываются на нижних уровнях системы. Хотя большинство параметров сокета можно установить с помощью setsockopt. Ссылка: man setsockopt А поскольку вы упоминаете только POSIX на любом Linux, в общем, в качестве своей области. accept() (Ссылка: man accept) имеет определенную свободу усмотрения в отношении того, какие параметры сокета должны быть унаследованы и какие параметры следует отклонить от прослушивающего fd.

accept () не изменяет исходный сокет, переданный ему в качестве аргумента. Новый сокет, возвращаемый методом accept (), не наследует флаги состояния файла, такие как O_NONBLOCK, O_ASYNC от слушающего сокета.

Таким образом, вместо того, чтобы полагаться на наследование или ненаследование свойств прослушивающего сокета (которое должно варьироваться в зависимости от реализаций и лицензий), принятый сокет должен быть явно установлен с желаемыми параметрами сокета (наилучшая практика)

man-страницы и коды реализации на вашем компьютере были бы наиболее подходящей спецификацией для поведения accept (). Не существует общей или стандартной спецификации, существующей в нескольких вариантах Linux.

4 голосов
/ 12 октября 2012

Нет, они не обязательно наследуются. Попробуйте этот пример, который устанавливает размер приемного буфера (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;
}

Результат на компьютере под управлением Linux 3.0.0-21-generic:

initial rcvbuf: 87380
set rcvbuf to 174760
accepted connection
new rcvbuf: 262142
3 голосов
/ 11 мая 2011

Socket options - это место, куда идут вещи, которые не подходят нигде. Таким образом, ожидается, что разные параметры сокетов будут по-разному наследовать поведение. Вопрос о том, наследовать или нет параметр сокета, определяется в каждом конкретном случае.

1 голос
/ 11 мая 2011

Было бы удивительно, если бы их не было.

Некоторые из них могут стать неактуальными после того, как сокет принял соединение, хотя (количество невыполненных запросов на соединение, например).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...