【问题标题】:Checking whether socket port is available检查socket端口是否可用
【发布时间】:2014-02-21 14:47:58
【问题描述】:

情况:

我有一个应用程序,其中包含一个 TCP 服务器(基于 socketserver),我想对其进行功能测试。

我为自己创建了一个测试 mixin,我在每个测试用例中都使用它:

class AppProcessManagingMixin:
    _used_tcp_ports = set()

    def start_my_app(self):
        port = self._take_tcp_port()
        prepare_config_with_given_tcp_port(port)
        # use prepared config by subprocess below
        Popen([python_executable_path, my_app_name, ...).start()

    def _take_tcp_port(self):
        available_found = False
        while not available_found:
            port = random.randint(9000, 9999) # these ints are arbitrary here
            available_found = port not in self._used_tcp_ports
        self._used_tcp_ports.add(port)
        return port

    def stop_my_app(self):
        so_something_that_Im_sure_will_stop_my_app_after_a_few_seconds()

每个测试用例setUp() 调用self.start_my_app(),每个tearDown() - self.stop_my_app(),我可以依靠停止我的应用程序。我需要我的应用程序的许多实例(并且无法在类范围的设置/拆卸中启动/停止应用程序),因为我的一些测试正在检查应用程序是否在从空工作目录开始的场景中运行良好(我只需要“空”应用程序实例用于这些测试)。

我对第二种方法有问题,_take_tcp_port。在介绍它之前,我经常遇到已获取地址的问题(因为所有测试都尝试在同一端口上运行 TCP 服务器)。现在它不再经常发生,但仍然 - 它发生了。

我知道它依赖于系统,几秒钟后端口将再次可用,但这会使自动化测试变得更加困难。

问题:

如何检查 TCP 服务器是否有可用的地址(主机和端口)?我想在_take_tcp_port 中检查它,以确保测试不会因为应用实例的占用端口问题而失败。

我所做的研究:

我浏览了以下 google 搜索的第一页:

  • 检查python端口是否打开
  • 检查python端口是否可用
  • 发现可用端口

以及我发现的所有方法都基于尝试获取套接字。问题是,如果我成功获得套接字,我可以确定这个端口是打开的,但是因为我这样做了,我不能确定我的应用程序能够获得它。我需要没有副作用的东西。

平台

这需要是多平台的(至少是 Windows、Linux、MacOS)。它必须至少在 p3.3+ 中工作。如果“有一个库”就足够了;)

【问题讨论】:

    标签: python sockets tcp


    【解决方案1】:

    您无需手动扫描可用端口 - 操作系统会为您完成。只需在调用 bind() 时指定端口 0,操作系统就会选择一个。这通常对测试很有用——您可以使用端口 0 启动一个端点,让它询问系统它实际获得的端口 (getsockaddr),然后使用该端口号启动第二个端点。

    【讨论】:

    • 这很有用,但是如何在 Popened 进程之外获取此端口?一些测试需要连接到这个 TCP 服务器,为了尽可能接近模拟现实生活场景,我想用 Popen 运行它,可能使用 shell=True,以隔离测试进程和应用程序进程(而不是调用它的 main () 函数在附加线程中的测试过程中,或 multiprocessing.Process)。
    • 一种选择是通过 Popen 将命令行参数传递给程序,该参数指定程序将在知道后立即写入端口号的文件的名称。或者甚至让您的启动器在任何端口上侦听并将该端口号传递给孩子,孩子将使用它来发回端口号。那个有点古怪,但如果你不愿意为此 IPC 使用文件系统,它会起作用。
    • 这意味着,我需要在应用程序中实现一些没有实际用途的东西,但只是为了测试而创建的。我认为这是不好的做法 - 我开始将应用程序逻辑和测试逻辑结合起来,这并不好。尽管如此,我们可能会添加一些存储使用过的配置(复制它)到工作区的东西,以便可以检查应用程序状态 - 然后,我们将使用这种方法。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2014-08-21
    • 2012-02-16
    • 2011-01-10
    • 1970-01-01
    • 2012-08-03
    • 2014-05-19
    • 1970-01-01
    相关资源
    最近更新 更多