“连接正常关闭。” IndyFtp“PUT”命令之后(Delphi-Indy FTP)

Hol*_*een 4 delphi ftp indy

我正在使用 Indy'sTIdFTP通过 FTP 从 Delphi 应用程序将压缩文件发送到服务器。该应用程序在数百台客户的计算机上使用。三个客户面临着同样的问题。执行命令后Put(),在 100% 传输的文件上传结束时,会出现“连接正常关闭”错误,并且上传的文件已损坏。

当从服务器下载 zip 文件并尝试打开它时,Winrar 说:

存档意外结束

附加信息:

  • 我开发了另一个测试应用程序来调试该问题。该错误发生在大小超过 300MB 的文件上。我测试上传文件从2MB到140MB没有问题。
  • 我在同一个局域网的另一台电脑上测试,结果是一样的。所以看来问题与调制解调器或互联网基础设施有关。计算机或调制解调器上没有活动防火墙,我在每台计算机上的调制解调器和 Windows 中禁用了防火墙。

源代码如下:

IdFTP1.Connect;
IdFTP1.TransferType := ftBinary;
IdFTP1.Put(strFileName);
IdFTP1.Disconnect;
Run Code Online (Sandbox Code Playgroud)

该错误发生在第三条语句上,并且它阻止与服务器断开连接。


附加说明:

正如雷米所说,我改变了一些东西,但结果是一样的。

  • NATKeepAlive通过如图所示的参数激活:

图像

我添加了finallyandexcept块,所以代码如下所示:

IdFTP1.Connect;
IdFTP1.TransferType := ftBinary;
try//finally
  try//except
    IdFTP1.Put(strFileName);
  except
  end;
finally
  IdFTP1.Disconnect;
end;
Run Code Online (Sandbox Code Playgroud)

更改后,程序执行Disconnect()命令,但上传的文件已损坏。当我想打开上传的 zip 文件时,Winrar 仍然显示“存档意外结束”,如下图所示:

图像

我启用了TIdLogFile我的TIdFTP连接。对一个小文件(14MB)和一个大文件(350MB)测试程序两次。上传的小文件工作正常,但上传的大文件已损坏。调试日志结果如下图:

小文件的日志文件 (14MB):

Stat Connected.
Recv 03/04/2023 10:29:31: 220 ProFTPD Server (ProFTPD) [***.***.***.***]<EOL>
Sent 03/04/2023 10:29:31: HOST ***.***.***.***<EOL>
Recv 03/04/2023 10:29:31: 220 HOST command successful<EOL>
Sent 03/04/2023 10:29:31: USER *******<EOL>
Recv 03/04/2023 10:29:31: 331 Password required for ******<EOL>
Sent 03/04/2023 10:29:31: PASS *******<EOL>
Recv 03/04/2023 10:29:31: 230 User ****** logged in<EOL>
Sent 03/04/2023 10:29:31: FEAT<EOL>
Recv 03/04/2023 10:29:31: 211-Features:<EOL>
Recv 03/04/2023 10:29:31:  AUTH TLS<EOL> CCC<EOL> CLNT<EOL>
Recv 03/04/2023 10:29:31:  EPRT<EOL> EPSV<EOL> HOST<EOL> LANG en-US.UTF-8*<EOL> MDTM<EOL> MFF modify;UNIX.group;UNIX.mode;<EOL> MFMT<EOL> MLST modify*;perm*;size*;type*;unique*;UNIX.group*;UNIX.groupname*;UNIX.mode*;UNIX.owner*;UNIX.ownername*;<EOL> PBSZ<EOL> PROT<EOL> RANG STREAM<EOL> REST STREAM<EOL> SIZE<EOL> SSCN<EOL> TVFS<EOL> UTF8<EOL>211 End<EOL>
Sent 03/04/2023 10:29:31: CLNT Indy 10.6.2.0<EOL>
Recv 03/04/2023 10:29:31: 200 OK<EOL>
Sent 03/04/2023 10:29:31: OPTS UTF8 ON<EOL>
Recv 03/04/2023 10:29:31: 200 UTF8 set to on<EOL>
Sent 03/04/2023 10:29:31: TYPE I<EOL>
Recv 03/04/2023 10:29:31: 200 Type set to I<EOL>
Sent 03/04/2023 10:29:31: SYST<EOL>
Recv 03/04/2023 10:29:31: 215 UNIX Type: L8<EOL>
Sent 03/04/2023 10:29:31: TYPE I<EOL>
Recv 03/04/2023 10:29:31: 200 Type set to I<EOL>
Sent 03/04/2023 10:29:31: PASV<EOL>
Recv 03/04/2023 10:29:31: 227 Entering Passive Mode (***.***.***.***,213,225).<EOL>
Sent 03/04/2023 10:29:32: MLSD _test<EOL>
Recv 03/04/2023 10:29:32: 150 Opening BINARY mode data connection for MLSD<EOL>
Recv 03/04/2023 10:29:32: 226 Transfer complete<EOL>
Sent 03/04/2023 10:29:32: CWD _test<EOL>
Recv 03/04/2023 10:29:32: 250 CWD command successful<EOL>
Sent 03/04/2023 10:29:32: PASV<EOL>
Recv 03/04/2023 10:29:32: 227 Entering Passive Mode (***.***.***.***,232,86).<EOL>
Sent 03/04/2023 10:29:32: STOR MySmallFile.zip<EOL>
Recv 03/04/2023 10:29:32: 150 Opening BINARY mode data connection for MySmallFile.zip<EOL>
Recv 03/04/2023 10:29:52: 226 Transfer complete<EOL>
Sent 03/04/2023 10:29:52: QUIT<EOL>
Recv 03/04/2023 10:29:52: 221 Goodbye.<EOL>
Stat Disconnected.
Run Code Online (Sandbox Code Playgroud)

大文件的日志文件 (350MB):

Stat Connected.
Recv 03/04/2023 10:30:51: 220 ProFTPD Server (ProFTPD) [***.***.***.***]<EOL>
Sent 03/04/2023 10:30:51: HOST ***.***.***.***<EOL>
Recv 03/04/2023 10:30:51: 220 HOST command successful<EOL>
Sent 03/04/2023 10:30:51: USER *********<EOL>
Recv 03/04/2023 10:30:51: 331 Password required for *****<EOL>
Sent 03/04/2023 10:30:51: PASS *********<EOL>
Recv 03/04/2023 10:30:51: 230 User ******** logged in<EOL>
Sent 03/04/2023 10:30:51: FEAT<EOL>
Recv 03/04/2023 10:30:51: 211-Features:<EOL> AUTH TLS<EOL> CCC<EOL> CLNT<EOL> EPRT<EOL> EPSV<EOL> HOST<EOL> LANG en-US.UTF-8*<EOL>
Recv 03/04/2023 10:30:51:  MDTM<EOL> MFF modify;UNIX.group;UNIX.mode;<EOL> MFMT<EOL> MLST modify*;perm*;size*;type*;unique*;UNIX.group*;UNIX.groupname*;UNIX.mode*;UNIX.owner*;UNIX.ownername*;<EOL> PBSZ<EOL> PROT<EOL> RANG STREAM<EOL> REST STREAM<EOL> SIZE<EOL> SSCN<EOL> TVFS<EOL> UTF8<EOL>211 End<EOL>
Sent 03/04/2023 10:30:51: CLNT Indy 10.6.2.0<EOL>
Recv 03/04/2023 10:30:51: 200 OK<EOL>
Sent 03/04/2023 10:30:51: OPTS UTF8 ON<EOL>
Recv 03/04/2023 10:30:51: 200 UTF8 set to on<EOL>
Sent 03/04/2023 10:30:51: TYPE I<EOL>
Recv 03/04/2023 10:30:51: 200 Type set to I<EOL>
Sent 03/04/2023 10:30:51: SYST<EOL>
Recv 03/04/2023 10:30:51: 215 UNIX Type: L8<EOL>
Sent 03/04/2023 10:30:51: TYPE I<EOL>
Recv 03/04/2023 10:30:51: 200 Type set to I<EOL>
Sent 03/04/2023 10:30:51: PASV<EOL>
Recv 03/04/2023 10:30:51: 227 Entering Passive Mode (***.***.***.***,213,173).<EOL>
Sent 03/04/2023 10:30:51: MLSD _test<EOL>
Recv 03/04/2023 10:30:51: 150 Opening BINARY mode data connection for MLSD<EOL>
Recv 03/04/2023 10:30:51: 226 Transfer complete<EOL>
Sent 03/04/2023 10:30:51: CWD _test<EOL>
Recv 03/04/2023 10:30:51: 250 CWD command successful<EOL>
Sent 03/04/2023 10:30:51: PASV<EOL>
Recv 03/04/2023 10:30:51: 227 Entering Passive Mode (***.***.***.***,222,56).<EOL>
Sent 03/04/2023 10:30:51: STOR MyBigFile.zip<EOL>
Recv 03/04/2023 10:30:51: 150 Opening BINARY mode data connection for MyBigFile.zip<EOL>
Sent 03/04/2023 10:40:24: QUIT<EOL>
Stat Disconnected.
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 10

FTP 协议使用多个 TCP 连接 - 一个用于主命令通道,一个用于数据通道上的每次传输。

当数据传输正在进行时,命令通道处于空闲状态。对于不知道 FTP 工作原理的网络系统来说,如果在长时间的数据传输过程中空闲时间过长,则断开命令通道的情况并不罕见。这可以解释为什么您只看到问题发生在大文件上,并且当尝试读取服务器的最终响应时,它可能表现为“连接正常关闭”错误(或许多其他套接字错误之一) 。TIdFTP.Put()

TIdFTP有一个NATKeepAlive属性可以帮助防止此问题,方法是在数据传输繁忙时在命令通道的 TCP 连接上启用 TCP 级保活。该NATKeepAlive.UseKeepAlive属性是False默认的。尝试将其设置为相反,并为和属性True设置合适的超时。这样,在数据传输期间,如果命令通道空闲了几毫秒,则每毫秒都会在命令 TCP 连接上传输 TCP keepalive 数据包,直到数据传输完成。NATKeepAlive.IdleTimeMSNATKeepAlive.IntervalMSIdleTimeMSIntervalMS