27 votes

WCF: System.Net.SocketException - Seule une utilisation de chaque adresse de socket (protocole/adresse réseau/port) est normalement autorisée

J'ai un service WCF et une application Web. L'application Web appelle ce service WCF de manière continue, c'est-à-dire en effectuant des appels successifs. Dans notre environnement de production, je reçois cette erreur très rarement. Comme il s'agit d'une activité interne, les utilisateurs ne sont pas au courant lorsque cette erreur se produit.

Impossible de se connecter à http://localhost/QAService/Service.svc. Code d'erreur TCP 10048: Seule une utilisation de chaque adresse de socket (protocole/adresse réseau/port) est généralement autorisée 127.0.0.1:80. ---> System.Net.WebException: Impossible de se connecter au serveur distant ---> System.Net.Sockets.SocketException: Seule une utilisation de chaque adresse de socket (protocole/adresse réseau/port) est généralement autorisée 127.0.0.1:80

J'ai du mal à reproduire ce comportement dans notre environnement de développement/QA. J'ai vérifié que la connexion client était fermée dans un bloc try..catch..finally. Je ne comprends toujours pas ce qui cause ce problème .. quelqu'un en sait plus à ce sujet ?

Note: J'ai consulté cette question SO, mais cela ne semble pas répondre à mon problème, donc il ne s'agit pas de questions répétées.

43voto

jrista Points 20950

Vous surchargez la pile TCP/IP. Windows (et je pense que toutes les piles de sockets en fait) ont une limitation sur le nombre de sockets qui peuvent être ouverts en séquence rapide en raison de la façon dont les sockets sont fermés en fonctionnement normal. Chaque fois qu'un socket est fermé, il entre dans l'état TIME_WAIT pendant un certain temps (240 secondes si je me souviens bien). À chaque fois que vous faites une requête, un socket est consommé dans la plage dynamique par défaut (je pense qu'il y a environ 5000 ports dynamiques juste au-dessus de 1024), et à chaque fin de demande, ce socket particulier entre en TIME_WAIT. Si vous faites suffisamment de requêtes, vous finirez par consommer tous les ports disponibles, ce qui entraînera une erreur TCP 10048.

Généralement, WCF essaie d'éviter ce problème en utilisant des pools de connexions et des choses comme ça. C'est généralement le cas avec les services internes qui ne vont pas sur internet. Je ne suis pas sûr si l'une des liaisons wsHttp prend en charge le pooling des connexions, mais la liaison netTcp devrait le faire. Je suppose que les named pipes n'ont pas ce problème. Je ne peux pas dire la même chose pour la liaison MSMQ.

Il y a deux solutions que vous pouvez utiliser pour contourner ce problème. Vous pouvez soit augmenter la plage de ports dynamiques, soit réduire la période de TIME_WAIT. La première option est probablement la plus sûre, mais si vous consommez un volume extrêmement élevé de sockets (ce qui ne semble pas être le cas pour votre scénario), réduire TIME_WAIT est une meilleure option (ou les deux ensemble.)

Changer la plage de ports dynamiques

  1. Ouvrez regedit.
  2. Ouvrez la clé HKLM\System\CurrentControlSet\Services\Tcpip\Parameters
  3. Modifiez (ou créez en tant que DWORD) la valeur MaxUserPort.
  4. Définissez-la sur un nombre plus élevé. (par exemple 65534)

Changer le délai TIME_WAIT

  1. Ouvrez regedit.
  2. Ouvrez la clé HKLM\System\CurrentControlSet\Services\Tcpip\Parameters
  3. Modifiez (ou créez en tant que DWORD) TcpTimedWaitDelay.
  4. Définissez-le sur un nombre plus bas. La valeur est en secondes. (par exemple 60 pour un délai d'attente d'1 minute)

Une des solutions ci-dessus devrait résoudre votre problème. Si le problème persiste après avoir modifié la plage de ports, essayez d'augmenter la période de vos requêtes pour qu'elles se produisent moins fréquemment... cela vous donnera plus de marge de manœuvre pour contourner le délai d'attente. Je modifierais le délai d'attente en dernier recours.

11voto

stimms Points 14986

HttpClient, bien qu'il implémente IDisposable est un objet partagé, vous devez réduire le nombre d'instances autant que possible. Vous pouvez vous en tirer en n'ayant qu'une seule instance pour toute la durée de vie de votre application plutôt que une pour chaque requête.

J'en ai écrit assez longuement à ce sujet sur http://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X