Python 多进程与套接字未关闭
我在使用Python的多进程和套接字时遇到了一些奇怪的情况。下面的代码和我正在处理的代码类似(我简化了很多,尽量让它看起来简单)。
这段代码创建了三个进程:一个进程什么都不做,另一个进程启动第三个进程,这个进程会在一个套接字上监听。如果我结束了“监听”进程,套接字仍然保持打开状态(我可以通过netstat看到它)。
- 如果我移除(或停止)“什么都不做”的进程,这样就没问题了。
- 如果我把所有东西都换成线程(threading.Thread),这样也没问题,但
- 如果我把“什么都不做”保持为进程,而把服务器和启动器换成线程,问题依然存在。
有没有人能告诉我为什么套接字仍然是打开的?在处理多进程和套接字时有没有什么问题?
我使用的是运行在Linux上的Python 2.6.6。
非常感谢,
阿尔瓦罗。
import time
from multiprocessing import Process, Event
import socket
class Server(Process):
def __init__(self, port):
super(Server, self).__init__()
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.s.bind(("127.0.0.1",port))
self.s.listen(1)
self.s.settimeout(10)
self.is_stop = Event()
self.is_stop.clear()
def run(self):
while not self.is_stop.is_set():
print "Server: running (pid %s)" % self.pid
time.sleep(1)
print "Server: exiting"
def stop(self):
self.is_stop.set()
self.s.close()
class Launcher(Process):
def __init__(self):
super(Launcher, self).__init__()
self.srv = Server(9999)
self.srv.start()
def run(self):
print "Launcher pid %s" % self.pid
while True:
time.sleep(1)
def stop(self):
print "Launcher: I'm stopping the server"
self.srv.stop()
self.srv.terminate()
self.srv.join()
print "Launcher: server stopped"
class DoNothing(Process):
def __init__(self):
super(DoNothing, self).__init__()
def run(self):
while True:
time.sleep(1)
l = Launcher()
l.start()
dn = DoNothing()
dn.start()
time.sleep(2)
print " Stop launcher "
l.stop()
while True:
time.sleep(1)
编辑:
相关的 netstat -lnp
输出:
tcp 0 0 127.0.0.1:9999 0.0.0.0:* LISTEN 7183/python
我注意到在netstat中显示的进程ID(pid)从父进程(当服务器进程运行时)变成了启动器的进程ID(当服务器停止时)。
2 个回答
1
我对 multiprocessing
这个包不是很精通,但看起来 Process
的构造函数是在父进程的环境下被调用的(也就是在进行 分叉之前)。如果真是这样,那就意味着在你的进程层级中,最上面的那个进程负责进行 bind
操作。子进程可能会继承这个套接字。
如果你把所有与 self.s
相关的内容(比如 bind
等)都放到 Server.run
里面,会发生什么呢?
3
要解决当前的问题(也就是套接字没有正常关闭),在 Server.stop
方法里加上 self.s.shutdown(socket.SHUT_RDWR)
这一行代码:
def stop(self):
self.is_stop.set()
self.s.shutdown(socket.SHUT_RDWR)
self.s.close()