dans l'un de mes projets J'ai implémenté un petit serveur HTTP pour diffuser les données vidéo d'une webcam connectée. Pour cette tâche, j'utilise le System.Net.Sockets.TcpListener de .NET Framework 4.5, qui écoute un point de terminaison préconfiguré et utilise le mtehod AcceptSocketAsync() pour attendre les requêtes entrantes. Vous pouvez voir les parties pertinentes du Code ci-dessous:C#: System.Net.Sockets.TcpListener ne ferme parfois pas Socket correctement
this.server = new TcpListener(endpoint);
this.server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(true, 0));
this.server.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
this.server.Start();
...
this.listenTask = Task.Factory.StartNew(this.Listen);
...
private async void Listen()
{
try
{
while (this.server.Server.IsBound)
{
Socket socket = await this.server.AcceptSocketAsync();
if (socket == null)
{
break;
}
Task.Factory.StartNew(() => this.ClientThread(socket));
}
}
catch (ObjectDisposedException)
{
Log.Debug("Media HttpServer closed.");
}
}
Cela fonctionne très bien, quand je démarre l'application et le serveur HTTP est démarré pour la première fois. Cependant, lorsque j'arrête le serveur HTTP (via CheckBox dans les paramètres de l'application), le socket d'écoute non-retourné n'est parfois pas fermé. Quand je vérifie l'état des sockets via la console (netstat -ano) je peux voir que le socket est toujours dans l'état LISTENING. Le problème qui en résulte est, lorsque je redémarre le serveur HTTP à nouveau, je reçois une System.Net.Sockets.SocketException avec le message "Une seule utilisation de chaque adresse de socket est normalement autorisée", ce qui n'est pas surprenant.
La partie de code correspondant pour arrêter le serveur HTTP est la suivante:
...
if (this.server != null)
{
if (this.server.Server != null)
{
if (this.server.Server.Connected)
{
this.server.Server.Shutdown(SocketShutdown.Both);
this.server.Server.Disconnect(true);
}
this.server.Server.Close();
}
this.server.Stop();
}
...
Je garde aussi la trace de mes connexions ouvertes et les fermer après avoir terminé la transmission de données et lors de l'arrêt du serveur. Aucune des sockets de connexion reste ouverte, donc je crois que seul le socket d'écoute devrait être pertinent pour ce problème. J'ai déjà essayé diverses combinaisons/commandes des méthodes Shutdown(), Disconnect(), Close() et Stop() lors de l'arrêt du serveur, ainsi que la définition/le désarmement de plusieurs options lors du démarrage du serveur comme Linger et ReuseAddress , qui semblait parfois résoudre le problème au début, mais quelques jours plus tard, le problème se reproduisait.
J'ai essayé aussi de « forcer » la prise d'écoute de fermer lors de l'arrêt du serveur à l'aide GetTcpTable (...) et SetTcpEntry (...) à partir iphlpapi.dll, comme décrit dans cette question: How to close a TCP connection by port? Malheureusement, l'approche n'a pas fonctionné pour moi (cela change tout à propos de l'état de la prise d'écoute du tout). Comme je suis un peu désemparé de ce que je pourrais faire d'autre, je demande ici si quelqu'un a une idée de ce qui pourrait causer le problème décrit ou comment le résoudre. Toute aide serait grandement appréciée.
Cordialement, Chris
Vous avez été victime du modèle de disposition superstitieuse. Vous disposez de beaucoup de façons et vérifiez toutes sortes de conditions. 'server.Dispose();' aurait été suffisant et n'aurait pas produit ce problème. – usr