Socket read timeout sous windows: hardcode étrange en méthode native

J’essayais de comprendre comment le délai de lecture des sockets est traité dans le code natif et j’ai trouvé une valeur étrange de 5000 millisecondes:

if (timeout) { if (timeout <= 5000 || !isRcvTimeoutSupported) { int ret = NET_Timeout (fd, timeout); ..... ..... } } 

Source: http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/windows/native/java/net/SocketInputStream.c

Comme je peux le voir, la variable isRcvTimeoutSupported est généralement définie sur true, mais pourrait être réduite à false lors de la définition des options de socket:

  /* * SO_RCVTIMEO is only supported on Microsoft's implementation * of Windows Sockets so if WSAENOPROTOOPT returned then * reset flag and timeout will be implemented using * select() -- see SocketInputStream.socketRead. */ if (isRcvTimeoutSupported) { jclass iCls = (*env)->FindClass(env, "java/lang/Integer"); jfieldID i_valueID; jint timeout; CHECK_NULL(iCls); i_valueID = (*env)->GetFieldID(env, iCls, "value", "I"); CHECK_NULL(i_valueID); timeout = (*env)->GetIntField(env, value, i_valueID); /* * Disable SO_RCVTIMEO if timeout is <= 5 second. */ if (timeout <= 5000) { timeout = 0; } if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout)) < 0) { if (WSAGetLastError() == WSAENOPROTOOPT) { isRcvTimeoutSupported = JNI_FALSE; } else { NET_ThrowCurrent(env, "setsockopt SO_RCVTIMEO"); } } ...... ...... } 

Source: http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/windows/native/java/net/TwoStacksPlainSocketImpl.c

Bien que je ne sois pas tout à fait sûr, il semble que le délai de lecture soit défini par des options de socket supérieures à 5 secondes et via NET_Timeout si elles sont inférieures ou égales à 5 secondes. Est-ce correct?

Et de toute façon, d’où viennent ces 5 secondes codées en dur?
Je ne vois aucune explication sur MSDN.

Ce code détermine comment implémenter un délai d’expiration de socket bloquant – que ce soit avec SO_RCVTIMEO ou avec select , car les sockets Windows prennent en charge les deux ( SO_RCVTIMEO n’est pas pris en charge sur toutes les plates-formes et toutes les implémentations Windows ne le prennent pas en charge) commentaire). NET_Timeout utilise select sous les couvertures.

Fondamentalement, l’algorithme est:

 if SO_RCVTIMEO is supported and timeout is more than 5 seconds: use SO_RCVTIMEO else: use select 

Quant à savoir d’où vient le seuil de 5 secondes, je suppose que, d’une manière ou d’une autre (via des tests ou des essais et erreurs?), Cette select est plus fiable ou plus précise pour les valeurs de délai d’attente inférieures à 5 secondes. Ce n’est pas que cela soit spécifiquement lié à ce problème (c’est pour un autre OS), mais voici un exemple de quelqu’un qui signale que SO_RCVTIMEO n’est pas fiable pour les petites valeurs de délai d’expiration.

Oui, vous avez lu le code correctement.

Il semble qu’il y ait une limite inférieure non documentée sur le délai d’expiration des sockets Windows, comme indiqué dans Pourquoi le délai d’attente sur un socket de réception Windows UDP est-il toujours 500ms plus long que celui défini par SO_RCVTIMEO?

J’imagine qu’ils ont atteint la limite lors des tests, qu’ils n’ont pas essayé de trouver la valeur exacte et ont donc choisi 5 comme limite inférieure connue.