bestsource

소켓 옵션이 리스닝 소켓에서 수락()을 통해 상속됩니까?

bestsource 2023. 11. 5. 14:49
반응형

소켓 옵션이 리스닝 소켓에서 수락()을 통해 상속됩니까?

청취 소켓이 다음과 같이 전달되었다고 가정합니다.accept기본값이 아닌 옵션이 설정되어 있습니다.setsockopt. 이러한 옵션(일부 또는 전부)이 승인된 연결에 대해 결과 파일 설명자에 의해 상속됩니까?

몇 가지 소켓 옵션은 시스템의 하위 레벨에서 처리됩니다.대부분의 소켓 옵션은 setsockopt를 사용하여 설정할 수 있습니다.참조:man setsockopt그리고 당신은 어떤 Linux 상에서도 POSIX만을 언급하고 있기 때문에, 일반적으로 당신의 범위로.accept()(참조:man accept)은 어떤 소켓 옵션을 이어받아야 하는지, 리스닝 fd로부터 어떤 옵션을 거부해야 하는지에 대해 어느 정도의 재량을 가지고 있습니다.

accept ()는 인수로 전달된 원래 소켓을 수정하지 않습니다.accept()에서 반환된 새 소켓은 수신 소켓에서 O_NONBLOCK,O_ASYNC와 같은 파일 상태 플래그를 상속하지 않습니다.

따라서 수신 소켓 속성의 상속 또는 비상속(구현 및 라이센스에 따라 달라질 수밖에 없음)에 의존하는 대신 허용된 소켓을 원하는 소켓 옵션으로 명시적으로 설정해야 합니다.(Best Practice)

man page와 기계의 구현 코드가 () 허용 동작과 가장 관련성이 높은 사양이 될 것입니다.리눅스의 여러 변종에 공통 사양이나 표준 사양이 존재하지 않습니다.

아니요, 꼭 유전되는 것은 아닙니다.수신 버퍼 크기()를 설정하는 이 샘플을 사용해 보십시오.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

소켓 옵션은 다른 곳에 맞지 않는 것들이 가는 곳입니다.따라서 소켓 옵션마다 상속 동작이 다를 것으로 예상됩니다.소켓 옵션 상속 여부는 케이스별로 결정됩니다.

제가 읽은 바로는 POSIX를 준수하는 구현에 대한 답은 아니오입니다.

POSIX-2017 사양에서 승인():

accept() 함수는 보류 중인 연결 대기열에서 첫 번째 연결을 추출하고 지정된 소켓과 동일한 소켓 유형 프로토콜 및 주소 패밀리로 새 소켓을 생성하며 해당 소켓에 대한 새 파일 설명자를 할당합니다.

명시적으로 "새 소켓"이지 "대기열이 해제된 소켓의 전체 또는 부분 복사본"이 아니므로 해당 소켓 유형 및 주소 패밀리의 기본값과 다른 옵션이 없어야 합니다.복사 동작이 바람직할 수도 있지만, 이는 플랫폼이 가질 수 있는 확장 인터페이스로 남겨집니다.하지만 어떤 플랫폼에서도 하나를 구현하는 것을 보지 못했기 때문에 표준에 추가될 수 있습니다.따라서 데이터를 보내거나 받기 위해 해당 소켓을 사용하기 전에 getsockopt()/setsockopt()를 사용하여 인터페이스의 책임이 아닌 큐 소켓에서 반환된 소켓으로 기본값과 다른 속성을 복사할 수 있습니다.

언급URL : https://stackoverflow.com/questions/5968132/are-socket-options-inherited-across-accept-from-the-listening-socket

반응형