2010-08-17 124 views
1

问候, 我已经在C#中定制了Telnet客户端。我正在使用它来与IMAP服务器进行通信。它只是写命令,然后得到响应。测试代码:从调用上面的代码如何同步读取/写入流?

  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(); 

输出是:

  1. 用户[email protected]
  2. + OK欢迎Atmail POP3服务器 - 登录与用户@域。
  3. +确定需要密码。
  4. PASS密码
  5. 退出
  6. + OK登录。
  7. + OK再见。

这是一个简单的例子,但它显示了一个竞争条件的问题。第nr.6行的输出应该出现在nr之前。 5

问:如何处理?

+0

似乎它做得很好。服务器在完成登录用户之前会收到退出消息。 – 2010-08-17 13:09:01

+0

这是可能的。反应是相当随机的。这取决于连接速度,服务器响应时间,返回的数据量。一旦有更多的命令请求更大的流,它会变得非常混乱。一般而言,Reads比Writes慢得多。 – asyncpro 2010-08-17 13:51:42

回答

0

我已经手动编写过我自己的telnet客户端。我处理命令的方式是为每个命令写入一个流,输入和预期的响应(我期望的部分回复,在你的情况下+确定)。这将允许我发送命令并等待响应。如果没有收到响应或不匹配,则抛出异常。

Telnet每个命令可以发送很多响应(空白,页面更改,登录流等)。所以等待你的预期回应是必要的。

+0

这不会在这里工作。有许多服务器,这个程序必须工作(我在ISP业务)。欢迎提供更一般的解决方案我正在考虑多线程和锁定资源,但不知道如何做到这一点。 – asyncpro 2010-08-17 13:57:56

+0

没有看到多服务器环境如何不能使用这种方法。请解释...您每次只能连接到一个Telnet实例。对?在封装了我需要的所有命令之后,我将Telnet facade作为WCF服务公开,并管理到Telenet服务器的连接池。 – CkH 2010-08-17 14:15:23

1

首先,IMAP邮件服务器不会说Telnet。 Telnet是TCP上的协议。见RFC 854。然而,Telnet客户端的优点在于,它作为一个非常小的协议,在原始TCP套接字之上,因此您可以连接到许多服务并与许多服务进行交互,这些服务在TCP上使用文本命令/响应样式协议(POP3,IMAP, SMTP,HTTP等)。

最终,您应该使用“现成的IMAP客户端”。做一些随机的谷歌搜索引导我到this one。我不知道这是否是好的,但可能会导致你的胜利。

如果您想要学习如何正确完成TCP/IP网络,您必须了解有关双向IO的一些基础知识。

您在这里遇到的情况很正常。 TCP套接字上有两个通道。一个用于阅读,一个用于写作。这些通道是独立的并可能被缓冲。

缓冲意味着,仅仅因为您在客户端代码中向发送套接字写入了一些数据(一行或任何)并不意味着它已在另一端收到。

因此,写入后立即阻止读取可能意味着您的命令永远不会发送,您将永远阻止读取。

此外,您可以像操作系统和带宽一样快地将命令写入发送套接字。只要服务器处理它们,答复就会回来。这可能很快,或者从未。就其性质而言,套接字编程是异步的并且容易失败(您正在通过不可靠的网络处理远程系统)。

处理异步双向IO的常用方法是有两个线程。一个用于阅读,另一个用于写作。当你不得不协调两个线程之间的请求&响应的“聊天”时,才开始“乐趣”。像AutoResetEvent和ManualResetEvent这样的线程原语可以在这里帮助。虽然你可能会尽最大努力去看C# Reactive Extensions,因为他们可以使工作变得更简单。我想建议reading up on the topic。即使对于诸如SMTP & POP3的“简单”协议,编写良好的无错误网络代码也不是微不足道的。

如果您不想使用C#作为您的解决方案,而只是尝试自动执行一些简单的Telnet服务交互,那么您应该查看Linux/Unix实用程序expect,它可以为您节省大量时间。

+0

谢谢,我一定会检查以上所有内容。 – asyncpro 2010-08-18 07:23:53