【问题标题】:Picking which ip address to use for ftp connection选择用于 ftp 连接的 IP 地址
【发布时间】:2016-07-05 00:07:40
【问题描述】:

我有一个问题。我的 NIC 有几个辅助 IP 地址。 我无法在 python 中找到一个用于 ftp 的库,该库允许选择用于连接 ftp 服务器的 IP 地址。 有谁知道它是如何实现的,我查看了原始套接字并没有找到它。 我知道它是在 jmeter 中为 http/https 实现的,但由于某种原因不是为 ftp 实现的。

感谢任何帮助。

【问题讨论】:

  • 我不认为这样的库存在。同样在 .NET 中,如果您是客户端,则无法选择要通过哪个连接出去。只需调用 Connect,您就会通过“活动连接”出去。
  • 标准 python ftp 库有一个source_address 参数。
  • @spectras 原来它没有向后移植到 python 2

标签: python networking ftp ip


【解决方案1】:

正如我提到的,标准的 python ftp 库有一个 source_address 参数。但是它不适用于您显然需要的 python 2。

所以我建议 python2.7 使用以下内容。这是 source_address 参数的复制粘贴 python3 实现并对其进行调整以使其工作。丑不过……

import ftplib
import socket

class FTP(ftplib.FTP):
    # KLUDGE, MANUAL BACKPORT OF source_address
    #     => REMOVE WHEN MOVING TO PYTHON3

    def __init__(self, *args, **kwargs):
        self.source_address = kwargs.pop("source_address", None)
        super(FTP, self).__init__(*args, **kwargs)

    def connect(self, host='', port=0, timeout=-999, source_address=None):
        if host != '':
            self.host = host
        if port > 0:
            self.port = port
        if timeout != -999:
            self.timeout = timeout
        if source_address is not None:
            self.source_address = source_address
        self.sock = socket.create_connection((self.host, self.port), self.timeout,
                                             self.source_address)
        self.af = self.sock.family
        self.file = self.sock.makefile('rb')
        self.welcome = self.getresp()
        return self.welcome

    def ntransfercmd(self, cmd, rest=None):
        size = None
        if self.passiveserver:
            host, port = self.makepasv()
            conn = socket.create_connection((host, port), self.timeout,
                                            self.source_address)
            try:
                if rest is not None:
                    self.sendcmd("REST %s" % rest)
                resp = self.sendcmd(cmd)
                if resp[0] == '2':
                    resp = self.getresp()
                if resp[0] != '1':
                    raise ftplib.error_reply, resp
            except:
                conn.close()
                raise
        else:
            sock = self.makeport()
            try:
                if rest is not None:
                    self.sendcmd("REST %s" % rest)
                resp = self.sendcmd(cmd)
                if resp[0] == '2':
                    resp = self.getresp()
                if resp[0] != '1':
                    raise ftplib.error_reply, resp
                conn, sockaddr = sock.accept()
                if self.timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
                    conn.settimeout(self.timeout)
            finally:
                sock.close()
        if resp[:3] == '150':
            size = ftplib.parse150(resp)
        return conn, size

这和猴子补丁一样丑陋。它应该可以解决问题。如果您使用它,请记录下这种恐怖,以便在您迁移到 python3 时将其删除。

【讨论】:

  • (注意:我刚刚修复了导入,如果您在我编辑之前复制粘贴,请再次复制)
  • 它可以解决问题,但我不确定我们是否迁移到 python 3,python 2 中有很多代码
【解决方案2】:

spectras 所述,Python 3 标准库中的 FTP 客户端允许将 source address 指定为元组。除非您有源的已知或静态端口,否则将端口号设置为零应该选择下一个可用端口。以文档为例:

from ftplib import FTP

source = ('192.168.1.100', 0)
destination = '172.16.1.1'
with FTP(destination, source_address=source) as ftp:
    ftp.login()
    print(ftp.dir())

【讨论】:

  • 不错的答案,只有 python 3 吗?
  • 刚查了一下,python 2不支持source_address(
猜你喜欢
  • 1970-01-01
  • 2013-10-31
  • 2011-08-01
  • 1970-01-01
  • 2015-03-29
  • 1970-01-01
  • 1970-01-01
  • 2017-02-13
  • 1970-01-01
相关资源
最近更新 更多