Les options de socket sont-elles héritées de accept () à partir du socket d’écoute?

Supposons que le socket d’écoute passé à accept ait des options non définies par défaut définies avec setsockopt . Ces options (certaines ou toutes?) Sont-elles héritées des descripteurs de fichiers obtenus pour les connexions acceptées?

Plusieurs des options de socket sont gérées aux niveaux inférieurs du système. Bien que la plupart des options de socket puissent être définies à l’aide de setsockopt. Référence: man setsockopt Et puisque vous ne mentionnez que POSIX sous Linux, en général, en tant que domaine. accept() (Référence: man accept ) dispose d’une certaine marge de manœuvre quant aux options de socket à hériter et aux options à rejeter du fd en écoute.

accept () ne modifie pas le socket d’origine qui lui est transmis en tant qu’argument. Le nouveau socket renvoyé par accept () n’hérite pas des indicateurs d’état du fichier tels que O_NONBLOCK, O_ASYNC du socket en écoute.

Par conséquent, au lieu de s’appuyer sur l’inheritance ou sur le non-inheritance des propriétés du socket d’écoute (qui varie selon les implémentations et les licences), le socket accepté doit être défini explicitement avec les options de socket souhaitées.

Les pages de manuel et les codes d’implémentation de votre ordinateur seraient la spécification la plus pertinente pour le comportement accept (). Aucune spécification standard ou commune n’existe entre plusieurs variantes de Linux.

Non, ils ne sont pas nécessairement hérités. Essayez cet exemple, qui définit la taille du tampon de réception ( SO_RCVBUF ) du socket initial sur une valeur autre que celle par défaut, puis compare le résultat au socket hérité. Exécutez ce code, qui écoute sur le port TCP 12345, puis connectez-vous à partir de tout autre programme.

 #include  #include  #include  #include  #include  #include  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; } 

Résultat sur une machine exécutant Linux 3.0.0-21-generic:

 initial rcvbuf: 87380 set rcvbuf to 174760 accepted connection new rcvbuf: 262142 

Les options de sockets sont l’endroit où les choses ne vont pas ailleurs. Ainsi, il est prévu que différentes options de socket aient un comportement d’inheritance différent. Qu’il s’agisse d’hériter ou non d’une option de socket est décidé au cas par cas.

Ce serait étonnant s’ils ne l’étaient pas.

Certaines d’entre elles peuvent toutefois perdre leur pertinence une fois que le socket a accepté une connexion (nombre de demandes de connexion en attente, par exemple).