2010-08-17 5 views
1

Salutations, J'ai un client Telnet personnalisé en C#. Je l'utilise pour communiquer avec les serveurs IMAP. Cela fonctionne comme une simple commande d'écriture, puis une réponse. Code d'essai:Comment synchroniser la lecture/écriture au flux?

  Telnet tc = new Telnet(); 
      // setup server credentials 
      const string server = "pop.nexlink.net"; 
      const int port = 140; 
      const int timeout = 70; 
      // establish server connection 
      tc.Setup(server, port, timeout); 
      // test initial server response 
      Console.WriteLine(tc.output); 

      // set-up a few commands to send 
      var array = new[] { "USER [email protected]", "PASS password", "QUIT" }; 

      // while connected to server 
      if (tc.IsConnected) 
      { 
       foreach (string str in array) 
       { 
        // Show command on console 
        Console.WriteLine(str); 
        // Write to Stream 
        tc.WriteLine(str); 
        // Read from Stream 
        tc.Read(); 
        // Test the Stream output 
        Console.Write(tc.output); 
       } 


      } 
      // close connection 
      tc.Disconnect(); 

Sortie d'appeler code ci-dessus est:

  1. UTILISATEUR [email protected]
  2. + OK Bienvenue sur le serveur POP3 Atmail - Connexion avec @ domaine utilisateur.
  3. + OK Mot de passe requis.
  4. PASS mot de passe
  5. QUIT
  6. + OK connecté.
  7. + OK Au revoir.

Ceci est un exemple simpliste, mais il montre un problème de condition de course. La sortie de la ligne n ° 6 devrait apparaître avant nr. 5

Q: Comment gérer cela?

+0

On dirait que ça va bien. Le serveur reçoit le message Quitter avant la fin de la connexion de l'utilisateur. –

+0

C'est possible. La réponse est plutôt aléatoire. Cela dépend de la vitesse de connexion, du temps de réponse du serveur, de la quantité de données à retourner. Cela devient vraiment désordonné quand il y a plus de commandes demandant chacune de plus gros flux. En général, les lectures sont beaucoup plus lentes que les écritures. – asyncpro

Répondre

0

J'ai manuellement écrit mes propres clients Telnet dans le passé. La façon dont j'ai géré les commandes consistait à écrire un flux pour chaque commande, avec des entrées et des réponses attendues (partie de la réponse que j'attendais, dans votre cas + OK). Cela me permettrait d'envoyer des commandes et d'attendre la réponse. Si la réponse n'a pas été reçue ou n'a pas correspondu, alors lancez une exception.

Telnet peut envoyer plusieurs réponses par commande (espaces, modifications de page, flux de connexion, etc.). Donc, l'attente de votre réponse attendue est nécessaire.

+0

Ça ne marchera pas ici. Il y a beaucoup de serveurs pour lesquels ce programme doit fonctionner (je suis dans les affaires d'ISP). Une solution plus générale est la bienvenue. Je pensais au multithreading et au verrouillage des ressources, mais je ne sais pas comment faire. – asyncpro

+0

Ne pas voir comment l'environnement multi-serveur ne fonctionnera pas avec cette approche. Veuillez expliquer ... Vous n'êtes toujours connecté qu'à une seule instance Telnet à la fois. Droite? Après avoir encapsulé toutes les commandes dont j'ai besoin, j'expose la façade Telnet en tant que service WCF et gère un pool de connexions au serveur Telenet. – CkH

1

Tout d'abord, un serveur de messagerie IMAP ne parle pas Telnet. Telnet est un protocole au-dessus de TCP. Voir RFC 854. La vertu des clients Telnet est cependant que Telnet est un protocole très minimal au-dessus des sockets TCP brutes, vous pouvez donc vous connecter et interagir avec de nombreux services qui utilisent également des protocoles de style commande/réponse texte sur TCP (POP3, IMAP, SMTP, HTTP, etc.) En fin de compte, vous devriez probablement utiliser un "client IMAP standard". Faire une recherche Google aléatoire m'a conduit à this one. Je n'ai aucune idée si c'est bon mais cela peut conduire à des victoires rapides de votre part.

Si toutefois vous voulez apprendre comment faire correctement le réseautage TCP/IP, vous devez réaliser quelques principes de base concernant les E/S bidirectionnelles.

Ce que vous expérimentez ici est tout à fait normal. Il y a deux canaux sur un socket TCP. Un pour la lecture, un pour l'écriture. Ces canaux sont indépendants et potentiellement tamponnés. La mise en mémoire tampon signifie que le simple fait que vous ayez écrit des données (une ligne ou autre) dans la socket d'envoi de votre code client ne signifie pas qu'il a été reçu à l'autre extrémité.

Par conséquent, le blocage immédiat d'une lecture après une écriture peut signifier que votre commande n'est jamais envoyée et que vous bloquerez la lecture pour toujours.

De plus, vous pouvez écrire des commandes sur le socket d'envoi aussi vite que votre système d'exploitation et votre bande passante vous le permettront. Les réponses reviendront chaque fois que le serveur les traitera. Ce qui pourrait être bientôt, ou peut-être jamais.De par sa nature, la programmation des sockets est asynchrone et sujette à l'échec (vous avez affaire à un système distant sur un réseau non fiable après tout).

L'approche habituelle pour traiter les E/S bidirectionnelles asynchrones consiste à avoir deux unités d'exécution. Un pour la lecture, et un autre pour l'écriture. Le "fun" commence lorsque vous devez coordonner le "chat" de la demande & réponse entre les deux threads. Les primitives Threading telles que AutoResetEvent et ManualResetEvent peuvent vous aider ici. Bien que vous feriez probablement mieux de regarder le C# Reactive Extensions car ils pourraient rendre le travail beaucoup plus simple.

Dans l'ensemble, je suggérerais reading up on the topic. L'écriture d'un bon code réseau sans erreur est non triviale même pour les protocoles "simples" comme SMTP & POP3. Si vous n'êtes pas lié à l'utilisation de C# pour votre solution et que vous essayez simplement d'automatiser certaines interactions de service de style Telnet, vous devriez regarder l'utilitaire Linux/Unix expect, cela pourrait vous faire gagner beaucoup de temps.

+0

Merci, je vais certainement vérifier tout ce qui précède. – asyncpro

Questions connexes