.net - 在 C# 中使用异步套接字实现 FTP 客户端的问题

标签 .net asynchronous ftp sockets

(对不起我的英语不好))

我正在为使用 .NET 类的 FTP 服务器的简单请求编写一个类
System.Net.Sockets.Socket.Synchronous 函数(Socket.Connect、Socket.Send、Socket.Receive)工作正常。但是我需要异步操作才能从外部中断该过程。

我使用了 MSDN 中的一个示例:
http://msdn.microsoft.com/en-us/library/bew39x2a%28VS.80%29.aspx使用 Socket.BeginConnect/EndConnect 方法的异步连接运行良好。连接后,我立即使用 Socket.BeginReceive/EndReceive 方法从服务器收到响应字符串(请参见下面的代码)。

接下来,我需要以 FTP 命令“USER anonymous”的形式发送一个用户名。
使用方法 Socket.BeginSend/EndSend 异步发送此字符串
进展顺利。 FTP-server 接受请求,并且,应该是,给我发回字符串
331 用户名ok,需要密码”。 (为了调试,我正在使用本地 FTP 服务器,从日志中我可以看到发送了答案)但是由于某种原因使用方法 Socket.BeginReceive/EndReceive 接收服务器响应失败。

我调用 Socket.BeginReceive 方法,但没有合适的回调函数
调用并且程序“挂起”等待答案。以下是我用来接收服务器响应的代码片段(_ftp - 我的私有(private)类 FtpState 的对象,用于在异步操作中存储数据):


...
// Begin receiving data
IAsyncResult ar = (IAsyncResult)_ftp.socket.BeginReceive(
    _ftp.buffer, 0, FtpState.BUFFER_SIZE, 0,
    new AsyncCallback(ReceiveCallback), _ftp);
// Waiting one of the following events:
// - receiving complete
// - external abort event
WaitHandle[] events = new WaitHandle[] { abortEvent, ar.AsyncWaitHandle };
i = WaitHandle.WaitAny(events);
...
// Callback-function on data receive
private static void ReceiveCallback(IAsyncResult ar)
{
    FtpState ftp = (FtpState)ar.AsyncState;
    try
    {
        int size = ftp.socket.EndReceive(ar);
        if (size > 0)
        {
            ftp.sb.Append(Encoding.ASCII.GetString(ftp.buffer, 0, size));
            ftp.socket.BeginReceive(ftp.buffer, 0, FtpState.BUFFER_SIZE, 0,
                new AsyncCallback(ReceiveCallback), ftp);
        }
        else
        {
            ... this code branch never executes at all ... 
            // In MSDN example ManualResetEvent is used to signal
            // the end of data receiving:
            // receiveDone.Set();
            // Instead i am using the event of synchronization object:
            // ar.AsyncWaitHandle (see code above)
            // Actually, i tried MSDN version too, but problem remains
            // as callback-function never calls.
         }
    }
    catch
    {
        ...
    }
}
...

同样,上面的代码可以很好地在连接后立即得到答案。将任何 FTP 命令发送到服务器后,就会出现接收答案的问题。我尝试结契约(Contract)步/异步方法:使用异步方法连接/发送和使用同步方法接收 - 一切正常。

我还尝试使用 System.Net.Sockets.TcpClient 类(Socket 类的扩展),但异步接收的类似问题仍然存在。搜索网络并没有帮助我。

也许有人遇到过类似的问题?我将不胜感激任何建议!

PS:使用 FtpWebRequest 不适合我。

最佳答案

是的,我正在回答一个非常古老的帖子,但我在使用 MSDN 示例代码时遇到了同样的问题。

谢尔盖的原始代码:

if (size > 0)
        {
            ftp.sb.Append(Encoding.ASCII.GetString(ftp.buffer, 0, size));
            ftp.socket.BeginReceive(ftp.buffer, 0, FtpState.BUFFER_SIZE, 0,
                new AsyncCallback(ReceiveCallback), ftp);
        }

应改为:
if (size > 0)
        {
            ftp.sb.Append(Encoding.ASCII.GetString(ftp.buffer, 0, size));
            // Check Available property before passing off control
            if (ftp.socket.Available > 0) 
              ftp.socket.BeginReceive(ftp.buffer, 0, FtpState.BUFFER_SIZE, 0,
                new AsyncCallback(ReceiveCallback), ftp);
            else
              {
                // send the finished result somewhere
                myResult = ftp.sb.ToString();
                // tell your ManualResetEvent you are finished receiving
                receiveDone.Set();
               }
        }

你为什么问?好吧,正如 Sergey 指出的那样,在服务器发送其最终数据后没有调用 ReceiveCallback ——如果没有任何东西可以接收回调,则永远不会触发!

这是一个痛苦的发现......

关于.net - 在 C# 中使用异步套接字实现 FTP 客户端的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2281434/

相关文章:

c# - 使用 protobuf 序列化 ConcurrentQueue

c# - 在任务中返回 true 或 false 的异步方法

node.js - Node.js 和 MongoDb 中同步应用程序的结构

java - 在 spring 集成 ftp :inbound-channel-adapter 中将作业参数传递给过滤器

C# 查找文件上传到 FTP 的时间

c# - 在 service .net core 中获取 appsettings.json 值

.net - Visual Basic 数组的第一个元素

c# - .net/C# 中的网络

javascript - 如何正确构造异步程序以确保正确的结果?

macos - 可以使用 SFTP 服务器拥有虚拟用户吗?