Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python3套接字-在停止和重新运行程序时,是否可以保持套接字打开?_Python_Sockets - Fatal编程技术网

Python3套接字-在停止和重新运行程序时,是否可以保持套接字打开?

Python3套接字-在停止和重新运行程序时,是否可以保持套接字打开?,python,sockets,Python,Sockets,我一直在挠头,想知道这是否可行 我有一个服务器程序,它运行着来自全国各地的大约30个不同的套接字连接。我现在需要更新这个服务器程序,虽然客户端设备将自动重新连接,但它并不完全可靠 我想知道是否有办法将套接字对象保存到文件中?然后在服务器重新启动时加载它?或者在程序停止后强制保持套接字打开。这样,客户机就永远不会断开连接 真的可以在这里使用热插拔代码真的 否,套接字是属于进程的特殊文件句柄。如果关闭进程,运行时将强制关闭所有打开的文件/套接字。这不是Python特有的;这正是操作系统管理资源的方式

我一直在挠头,想知道这是否可行

我有一个服务器程序,它运行着来自全国各地的大约30个不同的套接字连接。我现在需要更新这个服务器程序,虽然客户端设备将自动重新连接,但它并不完全可靠

我想知道是否有办法将套接字对象保存到文件中?然后在服务器重新启动时加载它?或者在程序停止后强制保持套接字打开。这样,客户机就永远不会断开连接


真的可以在这里使用热插拔代码真的

否,套接字是属于进程的特殊文件句柄。如果关闭进程,运行时将强制关闭所有打开的文件/套接字。这不是Python特有的;这正是操作系统管理资源的方式

但是,现在您可以做的是动态地重新加载一个或多个模块,同时保持进程处于活动状态。当您有打开的套接字时,可能需要进行一些谨慎的管理,但理论上这应该是可能的。是的,Python实际上支持热交换代码

对“动态重新加载”做一些阅读和研究。Python 3中的
importlib
模块提供了用于:

重新加载以前导入的模块。参数必须是模块对象,因此它必须在导入之前已成功导入。如果您已经使用外部编辑器编辑了模块源文件,并且希望在不离开Python解释器的情况下试用新版本,那么这将非常有用


解决方案1。

至少在linux下,这可以通过一些进程魔法来实现(尽管我相信存在类似的windows api)。首先请注意,套接字不能存储在文件中。这些物体的性质是暂时的。但是你可以把它们放在一个单独的过程中。看看这个:

因此,实现这一目标的一种方法是:

  • 在某一点上创建一个“保管员”流程(确保该流程不是主流程的子流程,以便在主流程消失时它保持活动状态)
  • 使用
    SCM\u权限通过
    sendmsg()
    将所有套接字发送到keeper进程
  • 关闭主进程
  • 做你必须做的任何更新
  • 启动主进程
  • 从keeper进程中检索套接字
  • 关闭keeper进程
  • 然而,这个解决方案很难维护。您有两个独立的进程,不清楚哪个是主进程,哪个是从进程。因此,您可能需要在顶部安装另一个主进程。事情变得很快,更不用说安全问题了

    解决方案2。

    按照@gavinb的建议重新加载模块可能是一个解决方案。但是请注意,在实践中,这经常会破坏应用程序。除非您知道所使用的每个Python文件的代码,否则您永远不知道这些模块在幕后做什么。此外,它还对模块施加了一些限制,即它们必须是可重新加载的。例如,一些模块使用内联缓存,这使得重新加载变得困难

    此外,一旦模块加载到不同的模块中,它会保留对该模块的引用。因此,您不仅要重新加载它,还要更新之前加载它的每个其他模块中的引用。除非您在项目开始时就考虑到这一点,否则维护成本会很快上升(因此,每个
    导入
    都会被封装起来,以便于重新加载)。由同一进程中运行的两个不同版本的模块引起的bug(我想,从来没有出现过这种情况)极难找到

    无论如何,我会避免这样做

    解决方案3。


    这就是XY问题。与其保存套接字,不如在主服务器前面放置一个代理?在海事组织,这是最安全、同时也是最简单的解决方案。代理将与主服务器通信(例如,通过unix域套接字),并将缓冲数据,并在主服务器再次可用时自动重新连接到主服务器。也许你甚至可以重用一些现有的技术,例如nginx。

    我认为你的关键问题是如何
    热重新加载

    正如@gavinb所提到的,您可以
    importlib
    ,然后使用
    importlib.reload(module)
    动态地重新加载模块


    请小心,
    reload(param)
    的参数必须是一个模块。

    您尝试的内容听起来有点危险,我宁愿研究确保100%时间重新连接的方法。为什么客户端有时无法重新连接?
    如果关闭进程,运行时将强制关闭所有打开的文件/套接字。
    这不是真的。您可以在进程之间共享套接字。通常情况下,您可以使用子进程来完成此操作,但您甚至可以将其发送到一些不相关的进程:@freakish链接的页面与关闭同一进程中不同线程的套接字有关,这与此处描述的情况不同。现在,
    exit
    的标准行为是关闭文件描述符,其中包括套接字。这种行为并不排除显式共享文件描述符的其他机制(例如,使用
    fork
    sendmsg
    )。这并不是说同一个进程,对自己调用
    sendmsg
    完全没有意义-该进程已经可以访问其文件描述符。也许你读错了我之前发布的链接,并修复了它。至于我的评论:我只是对突出显示的句子发表评论。这是错误的。我可以关闭子进程,并且套接字仍处于活动状态。现在,你的答案是暗示一些不真实的东西。这一点非常重要,因为实际上,
    sendmsg
    为OP解决问题提供了一种方法。