服务器进程使得管道插座不立即关闭

服务器进程使得管道插座不立即关闭

问题描述:

我有以下的代码,服务器接受的网络连接,它传递给孩子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

我能看到的是'Server.run'将它放入队列后立即关闭套接字。所以那个套接字是从那以后关闭的队列。 – ForceBru

+0

@ForceBru不会,孩子可以正常使用它。 –

+0

你的问题是什么?为什么还有另一个过程?或者为什么套接字不关闭? “不关闭”是什么意思? – bnaecker

有趣的问题。

我不确定这是否有帮助,但我发现你的代码在开始时有点奇怪,因为使用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至少,当我跑它,和它的作品,我会期望它的工作。

+0

感谢您的回答。 python3支持通过Queue()发送套接字对象(从3.3开始)。 –

+0

我使用'c.shutdown(socket.SHUT_RDWR)'替换了'handle_request()'中的'c.close()',从而让你的代码在Ubuntu 16.04上运行得非常好。没有CLOSE_WAIT套接字或其他任何异常。 – Hannu

+0

谢谢,我知道关机是一种选择。 –