服务器进程启动者多处理管理器()使管道插座未立即关闭

2024-04-19 23:07:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我有以下代码,服务器接受网络连接,将其传递给子进程以使用Manager().Queue()

q = Manager().Queue()

class Server:

    def run(self, host, port):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind((host, port))
        s.listen(1)

        print('parent', os.getpid())

        while True:
            c, _ = s.accept()
            q.put(c)
            c.close()

def handle_request():
    print('child', os.getpid())
    while True:
        c = q.get()
        time.sleep(1)
        print(c.recv(4))
        c.close()

Process(target=handle_request, args=()).start()
Server().run('127.0.0.1', 10000)   

close没有按预期工作,我想这是因为Manager的服务器进程在该套接字上有一个引用,lsof -i已确认。怎么处理?我发现在Manager进程中没有关闭套接字的方法,shutdown可以做到这一点,但不是我想要的。在


Tags: run服务器hostcloseserverqueue进程os
1条回答
网友
1楼 · 发布于 2024-04-19 23:07:48

有趣的问题。在

我不确定这是否有帮助,但我发现您的代码在一开始有点奇怪,因为使用Manager().Queue()向另一个进程发送套接字对象听起来不受支持。可能是这样,但是向另一个进程发送文件描述符需要一些技巧。我对你的代码做了一些修改,就像我做的那样——基本上是减少和重建句柄。在

from multiprocessing import Manager, Process
from multiprocessing.reduction import reduce_handle, rebuild_handle
import socket
import os
from time import sleep

q = Manager().Queue()


class Server:
    def run(self, host, port):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind((host, port))
        s.listen(1)

        print('parent', os.getpid())

        while True:
            c, _ = s.accept()
            foo = reduce_handle(c.fileno())
            q.put(foo)
            c.close()


def handle_request():
    print('child', os.getpid())
    while True:
        bar = q.get()
        sleep(1)
        barbar = rebuild_handle(bar)
        c = socket.fromfd(barbar, socket.AF_INET, socket.SOCK_STREAM)
        print(c.recv(4))
        c.shutdown(socket.SHUT_RDWR)

Process(target=handle_request, args=()).start()
Server().run('127.0.0.1', 10000)

至少在我运行CLOSE_WAIT时,它不会留下任何套接字,而且它的工作方式与我预期的一样。在

相关问题 更多 >