2010-12-07 5 views
1

Voici ma peine:besoin d'une meilleure façon d'attendre entre envoyer et recevoir, UdpClient

J'ai une classe udp qui me permettent d'envoyer et recevoir des données d'un serveur de jeu.

Mais j'ai trouvé que le serveur n'autoriser qu'une seule requête par 500ms par client. donc si j'envoie deux requêtes à la suite, le serveur répond seulement au premier, et je n'ai aucun moyen de savoir que je n'obtiendrai pas la deuxième réponse.

Donc, j'ai fait un Mutex pour protéger la partie d'envoi, quand j'envoie des données, j'utilise un thread pour bloquer le mutex 500ms.

Cette classe est utilisée par les threads, c'est pourquoi j'utilise mutex.

Mais cela ne fonctionne pas vraiment bien, parfois la réception est bloquée. Je veux juste savoir si quelqu'un a une meilleure façon de le faire.

Merci et désolé pour mon anglais.

EDIT: Je ne peux pas utiliser le protocole tcp, j'ai besoin de faire cela avec udp. J'ai également besoin d'un moyen optimal, j'ai besoin d'obtenir les données de réception dès que possible à la forme de vue. Je regarde tous les sujets sur le net je trouve sur UDP et le filetage, mais ne trouve pas ce cas particulier.

Répondre

1

Si vous savez que vous ne pouvez envoyer qu'avec une certaine fréquence, pourquoi ne pas envoyer des appels bloquants. Et puis dormez pour le temps requis.

class UDP { 
    int _lastTime = 0; 
    int MIN_DELAY = 500; 

    public void send() { 
    lock(this) { 
     int duration = now() - _lastTime; 
     if (duration < MIN_DELAY) { 
     sleep(MIN_DELAY - duration); 
     } 
     realSend(); 
     _lastTime = now(); 
    } 
    } 
} 
+0

c'est vraiment intéressant, j'espère que cela fonctionnera, je vais essayer ce soir , de toute façon c'est mieux que ma première façon, merci! – Mackhdo

+0

Il y a un bug dans ce code, 'sleep (duration)' devrait être 'sleep (MIN_DELAY - duration)'. C'est en dehors du fait qu'il n'est pas C#;) – Doggett

+0

@Doggett: Correction du bug. C'était censé être un pseudo-code semblable à C#. Je peux répondre à la question sans passer du temps à chercher comment obtenir l'heure actuelle en millisecondes. Le code que j'ai fourni était la partie importante. – unholysampler

1

Avec UDP, vous ne devez jamais supposer que vous obtiendrez une réponse à un message donné que vous envoyez. Vous ne devez pas non plus supposer que le message sera effectivement reçu ou que plusieurs messages seront reçus dans le même ordre que vous les avez envoyés. C'est pourquoi UDP est vraiment seulement adapté aux protocoles qui peuvent tolérer la perte d'informations. Si vous voulez maintenir l'intégrité, vous devez autoriser les tentatives, à quel point vous auriez probablement mieux fait d'utiliser TCP (en supposant que vous aviez le choix en la matière.)

Sans plus d'informations sur les détails du protocole, il est difficile de recommander une bonne solution. S'il s'agit d'un simple type de message, vous pouvez simplement envoyer les messages d'interrogation à un intervalle fixe et gérer les réponses à mesure qu'elles arrivent, en ignorant toute relation que les réponses pourraient avoir avec les messages envoyés.

+0

J'ai édité pour être plus spécifique. J'ai besoin de la relation entre meesage envoyé et reçu, car je lie les données à un winform. Je n'ai pas accès à mon code en ce moment mais je peux plus tard, demandez-moi si vous voulez. – Mackhdo

+0

@Mackhdo, malheureusement, si le service auquel vous vous connectez ne répond pas de manière rapide et fiable, vous ne pouvez pas faire grand-chose d'autre que de réessayer jusqu'à ce que vous obteniez une réponse. Si la nouvelle tentative prend trop de temps, c'est un problème qui ne peut être résolu qu'au service. –

+0

je sais, je suis juste à la recherche d'une façon agréable et meilleure de le faire, parce que je ne peux pas attendre de l'aide ou du changement du fournisseur du service – Mackhdo

0

Comme d'autres l'ont souligné, il ne peut pas être supposé qu'un message UDP sera délivré. Cela provoque probablement la suspension de votre code sur la réception. Peut-être que le simple réglage du ReceiveTimeout du Socket sera suffisant pour votre application. Ou vous pouvez configurer une méthode (un peu plus complexe) de mise en file d'attente des messages à envoyer, en n'en envoyant qu'une tous les 500 ms, et en les réessayant après un certain temps jusqu'à ce que vous obteniez une réponse. Si j'allais cette route, je concevoir autour de ces points généraux:

  • Utiliser UDP asynchrone.
  • Construire une structure/classe pour les informations réelles à envoyer/recevoir (par exemple, MsgObject), y compris des informations sur la dernière fois qu'il a été transmis.
  • Utilisez ce MsgObject en tant qu'objet AsyncState.
  • Gérez une file d'attente/une liste de tous les objets MsgObjects actifs. c'est-à-dire les messages qui ont été demandés à envoyer, mais aucune réponse n'a été reçue. Avoir une minuterie simple pour vérifier la file d'attente/liste périodiquement (pas plus fréquemment que tous les 500ms dans votre cas) pour voir si il ya un nouveau message à envoyer ou un qui doit être renvoyé.
  • Dans la fonction de réception asynchrone, supprimez le MsgObject qui a reçu la réponse de la file d'attente/liste.
+0

merci pour votre réponse, mais j'ai déjà regardé partout sur le web, je suis conscient de la façon différente de faire un udpclient mais sans expliquer tout le but de mon projet ici, tout ce dont j'avais besoin, et j'étais spécifique, était une meilleure façon de faire ce que je fais déjà. – Mackhdo

Questions connexes