我有以下代码,服务器接受网络连接,将其传递给子进程以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
可以解决问题但不是我想要的。
答案 0 :(得分:1)
有趣的问题。
我不确定这是否有任何帮助,但我发现你的代码在开始时有点奇怪,因为使用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中留下任何套接字,并且它可以正常工作。