gpt4 book ai didi

delphi - Indy FTP、大文件和 NAT 路由器

转载 作者:行者123 更新时间:2023-12-03 14:54:23 25 4
gpt4 key购买 nike

我多年来一直使用 Indy 通过 FTP 传输文件,但一直未能找到解决以下问题的满意解决方案。

当用户在路由器后面上传大文件时,有时会发生以下情况:文件上传正常,但同时命令 channel 因超时而断开连接。通常,直接连接到服务器时不会发生这种情况,因为服务器“知道”数据通道上正在发生传输。但有些路由器并没有意识到这一点,并且命令 channel 已关闭。

许多程序会定期发送 NOOP 命令以保持命令 channel 处于事件状态,即使这不是标准 FTP 规范的一部分。我的问题:我该怎么做?我是否在 OnWork 事件中发送 NOOP 命令?这是否会以某种方式造成任何附带损害,例如我是否需要处理一些响应?我该如何最好地解决这个问题?

最佳答案

我们使用多种方法来处理此问题:(1) 启用TCP/IP keepalives在传输期间控制 channel 上,(2) 连接断开后正常恢复,(3) 支持恢复中断的传输。

许多 FTP 客户端会在一切空闲时发送 NOOP,但我不知道是否有在数据传输期间发送 NOOP,因为在这种情况下您需要处理响应,并且许多服务器不会发送他们返回,直到数据传输完成。

  1. Indy 10.5.8 (Delphi XE2) 本身支持 TCP/IP 保持事件。只需使用 TIdFTP 的 NATKeepAlive 属性即可。

    对于以前的版本,分配 OnDataChannelCreate/OnDataChannelDestroy 事件:

    const
    KeepAliveIdle = 2 * SecsPerMin;
    KeepAliveInterval = 2 * SecsPerMin;
    IOC_VENDOR = $18000000;
    SIO_KEEPALIVE_VALS = DWORD(IOC_IN or IOC_VENDOR or 4);

    type
    tcp_keepalive = record
    onoff: u_long;
    keepalivetime: u_long;
    keepaliveinterval: u_long;
    end;

    procedure TFtpConnection.DataChannelCreated(Sender: TObject;
    ADataChannel: TIdTCPConnection);
    var
    Socket: TIdSocketHandle;
    ka: tcp_keepalive;
    Bytes: DWORD;
    begin
    // Enable/disable TCP/IP keepalives. They're very small (40-byte) packages
    // and will be sent every KeepAliveInterval seconds after the connection has
    // been idle for KeepAliveIdle seconds. In Win9x/NT4 the idle and timeout
    // values are system wide and have to be set in the registry; the default is
    // idle = 2 hours, interval = 1 second.
    Socket := (FIdFTP.IOHandler as TIdIOHandlerSocket).Binding;
    if Win32MajorVersion >= 5 then begin
    ka.onoff := 1;
    ka.keepalivetime := KeepAliveIdle * MSecsPerSec;
    ka.keepaliveinterval := KeepAliveInterval * MSecsPerSec;
    WSAIoctl(Socket.Handle, SIO_KEEPALIVE_VALS, @ka, SizeOf(ka), nil, 0, @Bytes,
    nil, nil)
    end
    else
    Socket.SetSockOpt(Id_SOL_SOCKET, Id_SO_KEEPALIVE, Id_SO_True)
    end;

    procedure TFtpConnection.DataChannelDestroy(ASender: TObject;
    ADataChannel: TIdTCPConnection);
    var
    Socket: TIdSocketHandle;
    begin
    Socket := (FIdFTP.IOHandler as TIdIOHandlerSocket).Binding;
    Socket.SetSockOpt(Id_SOL_SOCKET, Id_SO_KEEPALIVE, Id_SO_False)
    end;
  2. 要在文件已成功传输的情况下正常恢复,只需在最后重新连接并执行SIZELIST即可获取文件大小。如果它们匹配,则文件已成功传输,您无需执行任何其他操作。如果服务器支持,您还可以发送XCRC命令来获取CRC值,以便与本地文件进行比较。

  3. 如果您想要真正强大,您还可以检查TIdFTP.CanResume。如果设置了,服务器支持REST命令,因此您可以通过将true传递给AResume参数来从上次中断的地方继续传输。 TIdFTP.Get/Put

关于delphi - Indy FTP、大文件和 NAT 路由器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2665788/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com