Apache FTPSClient 挂起数据传输

Apache FTPSClient hangs on data transfer

我们使用 org.apache.commons.net FTPClient 并希望添加 FTPSFTPSClient 的支持。

不幸的是,只要服务器发送 150 代码,传输就会挂起。

这是读取目录列表的尝试:

220 Welcome
AUTH TLS
234 Proceed with negotiation.
USER *****
331 Please specify the password.
PASS *****
230 Login successful.
TYPE I
200 Switching to Binary mode.
PBSZ 0
200 PBSZ set to 0.
PROT P
200 PROT now Private.
SYST
215 UNIX Type: L8
PASV
227 Entering Passive Mode (******).
LIST
150 Here comes the directory listing.

Unsupported or unrecognized SSL message

这是文件上传尝试:

220 Welcome
AUTH TLS
234 Proceed with negotiation.
USER *****
331 Please specify the password.
PASS *****
230 Login successful.
TYPE I
200 Switching to Binary mode.
PBSZ 0
200 PBSZ set to 0.
PROT P
200 PROT now Private.
PASV
227 Entering Passive Mode (******).
150 Ok to send data.

Read timed out
java.net.SocketTimeoutException: Read timed out

test 正在创建文件,但有一些虚假的有效负载和连接挂起,直到超时。

有趣的是,使用 javax.net.debug=all 选项,我可以看到最后写入的块:

javax.net.ssl|DEBUG|10|Test worker|2021-01-13 02:02:59.467 CET|SSLSocketOutputRecord.java:255|Raw write (
  0000: 16 03 03 01 93 01 00 01   8F 03 03 70 08 E3 CA EF  ...........p....
  0010: BD A1 F6 D4 9C 86 24 F0   89 00 D1 7A 34 89 5E FB  ......$....z4.^.
  0020: 8D 3D 40 AE BC A8 22 32   85 09 CB 20 80 AB 30 AD  .=@..."2... ..0.
  0030: A3 C4 8F C8 24 62 D5 85   9C FC 17 60 56 1D 91 54  ....$b.....`V..T
  0040: 59 E2 01 A6 F1 B2 EE E6   F8 08 1A EC 00 5A 13 01  Y............Z..
  0050: 13 02 C0 2C C0 2B C0 30   00 9D C0 2E C0 32 00 9F  ...,.+.0.....2..
  0060: 00 A3 C0 2F 00 9C C0 2D   C0 31 00 9E 00 A2 C0 24  .../...-.1.....$
  0070: C0 28 00 3D C0 26 C0 2A   00 6B 00 6A C0 0A C0 14  .(.=.&.*.k.j....
  0080: 00 35 C0 05 C0 0F 00 39   00 38 C0 23 C0 27 00 3C  .5.....9.8.#.'.<
  0090: C0 25 C0 29 00 67 00 40   C0 09 C0 13 00 2F C0 04  .%.).g.@...../..
  00A0: C0 0E 00 33 00 32 00 FF   01 00 00 EC 00 05 00 05  ...3.2..........
  00B0: 01 00 00 00 00 00 0A 00   12 00 10 00 17 00 18 00  ................
  00C0: 19 01 00 01 01 01 02 01   03 01 04 00 0B 00 02 01  ................
  00D0: 00 00 0D 00 28 00 26 04   03 05 03 06 03 08 04 08  ....(.&.........
  00E0: 05 08 06 08 09 08 0A 08   0B 04 01 05 01 06 01 04  ................
  00F0: 02 03 03 03 01 03 02 02   03 02 01 02 02 00 32 00  ..............2.
  0100: 28 00 26 04 03 05 03 06   03 08 04 08 05 08 06 08  (.&.............
  0110: 09 08 0A 08 0B 04 01 05   01 06 01 04 02 03 03 03  ................
  0120: 01 03 02 02 03 02 01 02   02 00 11 00 09 00 07 02  ................
  0130: 00 04 00 00 00 00 00 17   00 00 00 2B 00 09 08 03  ...........+....
  0140: 04 03 03 03 02 03 01 00   2D 00 02 01 01 00 33 00  ........-.....3.
  0150: 47 00 45 00 17 00 41 04   B4 84 79 54 04 7E 9C FD  G.E...A...yT....
  0160: 59 ED 51 E8 8D 82 FE 02   0A DA E4 91 10 AA D7 FB  Y.Q.............
  0170: 5E DE A9 0B 9A F7 F6 58   9D A3 D3 B6 1A 99 61 B8  ^......X......a.
  0180: 8F 6F 25 98 4A 12 5A 93   9D D6 64 2A A8 F2 DF D5  .o%.J.Z...d*....
  0190: 3E 33 69 49 7B B4 E6 6D                            >3iI...m
)
javax.net.ssl|WARNING|10|Test worker|2021-01-13 02:03:59.530 CET|SSLSocketImpl.java:1555|handling exception (
"throwable" : {
  java.net.SocketTimeoutException: Read timed out

最后一个块是作为文件内容保存在服务器上的内容,没有完成响应。

目前我不知道服务器是什么或它的配置,不幸的是它对我们来说是一个黑盒子。

这是我们的测试代码(简化了客户端设置部分,没有异常处理以减少post):

        val ftp = FTPSClient()

        ftp.addProtocolCommandListener(PrintCommandListener(PrintWriter(System.out)));
        ftp.connect(uri.host, uri.port)
        ftp.login(uri.username, uri.password)
        ftp.setFileType(FTP.BINARY_FILE_TYPE)
        ftp.enterLocalPassiveMode()
        ftp.execPBSZ(0)
        ftp.execPROT("P")

        //ftp.listFiles().forEach { println(it) }

        if (!ftp.storeFile("test", "test".byteInputStream())) {
            println("FTP server responded: ${ftp.replyCode} ${ftp.replyString}")
        }

可能是什么问题?是我们的代码(或 Apache 库)的错误还是某些服务器的不当行为?

虽然我不知道错误的来源是什么,但我将 Apache Commons Net 版本从 3.7 降级到 3.6 并且它起作用了。将尝试更深入地挖掘并可能找到更多细节,但解决方案是降级库版本。

-编辑-

我还用 3.7.2 进行了测试,现在它可以工作了,所以我们只是使用了一个有缺陷的版本的库 :)。