Auteur de questions
Timeout et socket asynchrone.

Discussion générale
-
Bonjour,
Lors d'échange de données entre un client et un équipement qui fait office de serveur. En cas de perte de connexion, j'ai remarqué qu'il y a un certains laps de temps bien déterminé qui s'écoule avant que le SendCallback (qui est executé par BeginSend) ne lance une exception.
Je voudrais savoir s'il y a un moyen de contrôler ce temps pour le réduire ou l'augmenter afin que je puisse gérer un timeout lors de l'envoie de données.
En effet, je démarre un timer avec un certain intervalle pour l'envoie de données et tant que je n'ai pas de Recieve pour stoper le timer, il y 'aura 3 trois tentatives d'envoi au bout des quels si je ne reçois toujours pas de réponse, je sais qu'il y un problème de connexion et dans ce cas je peux effectuer un traitement.
Or, si je peux le qualifier ainsi c'est que j'ai deux timeout à devoir gérer le mien et celui du SendCallback. Alors, je ne sais pas comment faire ?
Cordialement,
Beel
- Type modifié beela jeudi 10 octobre 2013 12:45 Rectification
- Type modifié Aurel Bera lundi 21 octobre 2013 07:43 Discussion
Toutes les réponses
-
Bonjour,
Je voudrais savoir s'il y a un moyen de contrôler ce temps pour le réduire ou l'augmenter afin que je puisse gérer un timeout lors de l'envoie de données.
Vous ne pouvez pas gérer un timeout des sockets avec les méthodes asynchrones.Vous devez donc gérer vous même le mécanisme de Timeout, voilà un moyen de le faire très simplement avec des tâches :
static void Main(string[] args) { Socket socket; socket = .... ; Task.Factory.StartNew(() => { Send(socket, new byte[] { ... }, 1000, OnSended); }); } static void OnSended() { // Donné reçue avant 1 seconde } static void Send(Socket socket, byte[] data, int timeOut, Action callback) { // Appeler la méthode Send() de manière asynchrone // via une tâche Task t; t = Task.Factory.StartNew(() => { socket.Send(data); }); // Attendre la tâche de "timeOut" millisecondes if (t.Wait(timeOut) == false) { // Si Wait() retourne false, c'est que la méthode Send() // n'a toujours pas répondu, fermer le socket socket.Close(); } else { // L'appel Send() s'est terminée avant les "timeOut" millisecondes, // appeler la méthode callback callback(); } }
Indiquez nous si cela correspond à votre besoin.
Cordialement
Gilles TOURREAU - MVP C#
Architecte logiciel/Consultant/Formateur Freelance
Blog : http://gilles.tourreau.fr
- MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
- MCITP : SQL Server 2008 Developper
- MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0 -
-
-
Bonjour,
Il faut dans ce cas récupérer votre socket et le fermer (en appelant la méthode Close()).
Cordialement
Gilles TOURREAU - MVP C#
Architecte logiciel/Consultant/Formateur Freelance - P.O.S Informatique
Blog : http://gilles.tourreau.fr - Suivez-moi sur Twitter
- MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
- MCSA : SQL Server 2012
- MCITP : SQL Server 2008 Developper
- MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0 / TFS 2010 / Windows Azure -
Bonjour,
Merci pour votre proposition. Mais, le Close ne répond à mon problème. Pour être plus précis, voici la situation:
En fait, j'ai une routine qui fait des Send toutes les secondes(sachant que je suis dans un état de socket.Connected), mais dès qu'une déconnexion se produit, je ne suis avertis de cette déconnexion que quelques secondes après par une exception générée par un RecieveCallback.
Entre temps plusieurs threads ont été crées puisque chaque Send déclenche un (socketListener.BeginSend(byteData, 0, byteData.Length, 0,new AsyncCallback(SendCallback), socketListener)).
C'est pourquoi, je pensais qu'il existait un moyen d'annuler ces SendCallback pour ne pas se retrouver avec une multitude de threads qui restent en suspens.
Finalement, la question est de savoir maintenant, s'il y a un moyen de vérifier l'état de connexion avant d'envoyer un éventuel Send ou de savoir comment être averti par cette déconnexion avant d'envoyer le Send suivant.
Cordialement,
Beel
- Modifié beela mercredi 16 octobre 2013 14:00 Précision
-
Bonjour,
Il n'est pas possible d'annuler l'ordre d'envoi ou de réception dans les Socket.
Entre temps plusieurs threads ont été crées puisque chaque Send déclenche un (socketListener.BeginSend(byteData, 0, byteData.Length, 0,new AsyncCallback(SendCallback), socketListener)).
Malheureusement, c'est à vous de gérer ce cas si vous utilisez des méthodes asynchrones... (Via un booléen qui indique que vous avez perdu la connexion. Il faudra aussi gérer le fait que le premier thread traite l'erreur et pas les autres grâce à ce booléen).Avez-vous essayé ma solution avec des tâches ? Il suffit juste de mettre un Wait() de 900 millisecondes...
Finalement, la question est de savoir maintenant, s'il y a un moyen de vérifier l'état de connexion avant d'envoyer un éventuel Send ou de savoir comment être averti par cette déconnexion avant d'envoyer le Send suivant.
Je ne suis pas sûre mais je crois que vous pouvez vous baser sur le booléen Connected du Socket. Il n'y a pas d'autre moyen de vérifier l'état de la connexion d'un Socket à part envoyer ou recevoir des données.Cordialement
Gilles TOURREAU - MVP C#
Architecte logiciel/Consultant/Formateur Freelance - P.O.S Informatique
Blog : http://gilles.tourreau.fr - Suivez-moi sur Twitter
- MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
- MCSA : SQL Server 2012
- MCITP : SQL Server 2008 Developper
- MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0 / TFS 2010 / Windows Azure -
Bonjour,
J'ai essayé votre solution avec la création de tâche, mais ça ne résout pas mon problème.
public void Send(byte[] byteData)
{
if (statutConnexion == true) // Connecté
{
Task.Factory.StartNew(() =>
{
SendDatas(socListener, byteData, 1000, OnSended);
});
}
else if (!IsConnecting)
{
TryToConnect();
}
}
private void SendDatas(Socket socket, byte[] byteData, int timeOut, Action callback)
{
try
{
Task taskSend;
taskSend = Task.Factory.StartNew(() =>
{
socListener.Send(byteData);
});
if (taskSend.Wait(timeOut) == false)
{
statutConnexion = false;
socListener.Close();
}
else
{
callback();
}
}
catch (Exception ex)
{
//
}
}
private void OnSended()
{
//Send Ok
}Même avec une perte de connexion avec le serveur, lors du Send le (t.Wait(timeout) n'est jamais à "false").
Donc, apparemment, il n' y a pas moyen de détecter une perte de connexion pendant l'execution d'un Send, si ce n'est d'être averti par un receiveCallBack qu'après que quelques secondes soient écoulées(20 à 25 secondes).
Or, moi je voudrai savoir que quand, il y a une connexion qui est établie et que j'envoie toutes les secondes un Send, l'un après l'autre et que dès qu'il y a une deconnexion, être averti avant d'envoyer le Send suivant sans attendre le receiveCallback. D'une autre manière, trouver un moyen de vérifier s'il y une connexion ou pas avant d'envoyer un Send.
Cordialement,
- Modifié beela jeudi 17 octobre 2013 11:06 correction
-
Bonjour,
Est-ce que vous utilisez le .NET Framework 4.0 ?
Je peux simplifier mon code afin de n'a pas utiliser les lambda expressions, mais il y a aura plus de ligne de code.
Vous utilisez BeginSend() et donc l'asynchronisme des socket qui ne permet pas de gérer des Timeout qui répondrait à votre problème. La solution est d'utiliser la méthode Send() de manière synchrone, et en parallèle attendre 1000 millisecondes. Si on n'a pas de réponse au bout de 1000 millisecondes on ferme la socket.
Cordialement
Gilles TOURREAU - MVP C#
Architecte logiciel/Consultant/Formateur Freelance - P.O.S Informatique
Blog : http://gilles.tourreau.fr - Suivez-moi sur Twitter
- MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
- MCSA : SQL Server 2012
- MCITP : SQL Server 2008 Developper
- MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0 / TFS 2010 / Windows Azure -
-
Bonjour,
Parceque les méthodes asynchrone de la classe Socket n'en tiennent pas compte.
Cordialement
Gilles TOURREAU - MVP C#
Architecte logiciel/Consultant/Formateur Freelance - P.O.S Informatique
Blog : http://gilles.tourreau.fr - Suivez-moi sur Twitter
- MCPD : Enterprise Developper / Windows Developper 3.5 / ASP .NET 3.5/4.0
- MCSA : SQL Server 2012
- MCITP : SQL Server 2008 Developper
- MCTS : ADO .NET 3.5 / SQL Server 2008 Developper / Windows Forms 3.5 / ASP .NET 3.5/4.0 / TFS 2010 / Windows Azure