我正在尝试在python3.3中实现一个服务器,该服务器预先加载了一个单独的线程来对传入连接进行所有处理。
from multiprocessing import Process, Pipe, Queue
from multiprocessing.reduction import reduce_socket
import time
import socketserver,socket
def process(q):
while 1:
fn,args = q.get()
conn = fn(*args)
while conn.recv(1, socket.MSG_PEEK):
buf = conn.recv(100)
if not buf: break
conn.send(b"Got it: ")
conn.send(buf)
conn.close()
class MyHandler(socketserver.BaseRequestHandler):
def handle(self):
print("Opening connection")
print("Processing")
self.server.q.put(reduce_socket(self.request))
while self.request.recv(1, socket.MSG_PEEK):
time.sleep(1)
print("Closing connection")
class MyServer(socketserver.ForkingTCPServer):
p = Process
q = Queue()
parent_conn,child_conn = Pipe()
def __init__(self,server_address,handler):
socketserver.ForkingTCPServer.__init__(self,server_address, handler)
self.p = Process(target=process,args=(self.q,))
self.p.start()
def __del__(self):
self.p.join()
server_address = ('',9999)
myserver = MyServer(server_address,MyHandler)
myserver.serve_forever()
我可以使用以下脚本测试它的工作原理:
from multiprocessing.reduction import reduce_socket
import time
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost', 9999))
time.sleep(1)
print("reduce_socket(s)")
fn,args = reduce_socket(s)
time.sleep(1)
print("rebuild_socket(s)")
conn = fn(*args)
time.sleep(1)
print("using_socket(s)")
conn.send("poks")
print conn.recv(255)
conn.send("poks")
print conn.recv(255)
conn.send("")
print conn.recv(255)
conn.close()
不幸的是,似乎有一些错误,因为在运行测试n次后,我的tmp文件夹中充满了子文件夹:
$ ls /tmp/pymp*|wc -l
32000
这些临时文件由socket_reduce()
创建。有趣的是,客户端中的rebuild/reduce_socket()
也会创建临时文件,但一旦函数退出就会删除它们。我当前的tmp文件系统中的最大文件夹数量是32000,这会导致出现问题。我可以手动或在服务器的某个地方删除/ tmp / pymp * -files,但我想也应该有正确的方法来做到这一点。任何人都可以帮我这个吗?
答案 0 :(得分:0)
好的,有点固定了。来自。./lib/python3.3/multiprocessing/util.py:
$ grep "def get_temp_dir" -B5 /usr/local/lib/python3.3/multiprocessing/util.py
#
# Function returning a temp directory which will be removed on exit
#
def get_temp_dir():
在进程退出之前,临时目录似乎应该可用。由于我的process()
和main()
都会永久运行,因此不会删除临时文件。要修复它,我可以创建另一个将reduce_socket传递给process()
:
def process(q):
while 1:
fn,args = q.get()
conn = fn(*args)
while conn.recv(1, socket.MSG_PEEK):
buf = conn.recv(100)
if not buf: break
conn.send(b"Got it: ")
conn.send(buf)
conn.close()
q.put("ok")
class MyHandler(socketserver.BaseRequestHandler):
def socket_to_process(self,q):
q.put(reduce_socket(self.request))
q.get()
def handle(self):
p = Process(target=self.socket_to_process,args=(self.server.q,))
p.start()
p.join()
这样一来,临时文件就会在一个子进程中创建,一旦process()
用输入完成它就会退出。我不认为这是一种优雅的方式,但它的工作原理。如果有人知道更好,请告知stackoverflow。