Подтвердить что ты не робот

Есть ли опции сокета, унаследованные в accept() из прослушивающего сокета?

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

Ответ 4

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

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