Python 的 ftplib 损坏发送的文件 - Winsock 问题?

Python's ftplib corrupting sent files - Winsock issue?

我们有一个 Python 应用程序,用于在 PC 上的 SVN 签出和 IBM i 中端系统之间来回传输源文件。

它已经使用了很多年,没有任何问题。

最近,我们开始看到源文件在从 PC 发送到 IBM i 时被损坏。目的地的线路乱序。 Wireshark 表明数据正在离开 PC。

有时很好用,有时是一两行乱,有时是很多行。

在出现此问题之前脚本没有更改。

这是 Python 代码中的 storlines() 调用:

connection.storlines('STOR ' + ibmi_file, open(source_file.fullpath, 'rb'))

最初,我在 Windows 10 上使用 Python 2.7.12。我尝试升级到 2.7.13,但我仍然看到问题。我尝试移动到 3.6.1,但我仍然看到问题。

其他开发人员也看到了这个问题,运行 Python 和 Windows 的各种版本。

我下载了 3.6.1 源代码并在 socketmodule.c

中的 sock_sendall() 和 sock_send_impl() 添加了一些调试日志记录

我可以看到从 sock_send_impl() 发送了以下内容。

来源
line# - 长度(字节)
1 - 79
2 - 73
3 - 38
4 - 73
5 - 78
6 - 41

Wireshark 显示以下 FTP 个数据包。

数据包# - FTP数据长度
1 - 79
2 - 1452

问题是数据包 2 以源代码行开始:

2、5、3、4

据我了解,sock_send_impl() 是将数据传递给 OS 的地方。我意识到 Nagle's algorithm 用于将小发送组合成一个较大的 TCP 数据包。

但是该数据包中的数据应该与传递给发送的顺序相同。而事实并非如此。

我认为这可能与最近的一些 Windows 补丁有关,只是我们的一位开发人员使用 Mac 遇到了同样的(?)问题。

我们确实有一位开发人员 运行 Windows 7 至少报告没有看到这个问题(他已经出去了)。

这对我来说没有任何意义,我不知道从这里到哪里去。

我们有理由确定问题是由 Symantec Vontu 14.6 MP1 版引起的;这是一种数据丢失防护 (DLP) 产品,"inspects" 在离开 PC 之前对其进行打包。

我相信该问题已报告给 Symantec。

与此同时,我们通过扩展基础 ftplib.FTP class 并添加新函数解决了这个问题:

#stortext combines block read from STORBINARY with ASCII transfer mode from STORLINE
def stortext(self, cmd, fp, blocksize=8192, callback=None, rest=None):
    self.voidcmd('TYPE A')
    conn = self.transfercmd(cmd, rest)
    while 1:
        buf = fp.read(blocksize)
        if not buf: break
        conn.sendall(buf)
        if callback: callback(buf)
    conn.close()
    return self.voidresp()

我们不再遇到乱码问题。作为奖励,传输 运行 比 storline.

快得多

所以我们继续使用我们的新功能。