如何同步读/写到流?

时间:2010-08-17 13:00:19

标签: c# synchronization telnet

问候, 我在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 AppChecker@nexlink.net", "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. USER AppChecker@nexlink.net
  2. + OK欢迎使用Atmail POP3服务器 - 使用user @ domain登录。
  3. +确定需要密码。
  4. 通过密码
  5. QUIT
  6. +确定已登录。
  7. + OK Bye-bye。
  8. 这是一个简单的例子,但它显示了竞争条件的问题。第nr行的输出应出现在nr之前。 5

    问:如何处理?

2 个答案:

答案 0 :(得分:1)

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

最终你应该只使用“现成的IMAP客户端”。进行一些随机的Google搜索会引导我this one。我不知道它是否好,但它可能导致你的快速胜利。

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

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

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

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

此外,您可以像操作系统和带宽一样快地将命令写入发送套接字。只要服务器处理它们,回复就会回来。哪个可能很快,也许永远不会。就其本质而言,套接字编程是异步的并且容易出现故障(您正在通过不可靠的网络处理远程系统)。

处理异步双向IO的常用方法是使用两个线程。一个用于阅读,另一个用于写作。当你必须协调请求的“聊天”时,“乐趣”就开始了。两个线程之间的响应。像AutoResetEvent和ManualResetEvent这样的线程原语在这里可以提供帮助。虽然你可能最好看看C# Reactive Extensions因为它们可以使这项工作变得更加简单。

总的来说,我建议reading up on the topic。编写好的无错误网络代码即使对于“简单”协议(如SMTP& POP3。

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

答案 1 :(得分:0)

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

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

相关问题