解釋
我正在用python3中的套接字做一個架構服務器-多客戶端。
為此,我使用多處理庫。代碼如下,創建一個服務器監聽客戶端連接:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("",PORT))
sock.listen(CLIENTS)
print(logFile().message(f"running ClassAdmin server, listen {CLIENTS} clients by port {PORT}...",True,"INFO"))
sockSSL = context.wrap_socket(sock,server_side=True)
while sockSSL:
connection, address = sockSSL.accept()
eventChildStop = multiprocessing.Event()
subprocess = multiprocessing.Process(target=ClientListener, name="client", args=(connection, address))
subprocess.start()
在上面的代碼中,每個客戶端都在一個行程子行程中執行。和multiprocessing.Process()
這運行類ClientListener。
class ClientListener:
def __init__(self,conn,addr):
try:
self.conn, self.addr = conn, addr
self.nick = ""
self.__listenData()
except (KeyboardInterrupt,SystemExit) as err:
print(logFile().message(f"The host {self.nick} ({self.addr[0]}:{self.addr[1]}) left", True, "INFO"))
except BaseException as err:
type, object, traceback = sys.exc_info()
file = traceback.tb_frame.f_code.co_filename
line = traceback.tb_lineno
print(logFile().message(f"{err} in {file}:{line}", True, "ERROR"))
finally:
try:
ListClients().remove(self.conn)
self.conn.close()
except:
None
finally:
Client(self.conn,self.addr).registre(self.nick,"DISCONNECTED",False)
def __listenData(self):
while True:
data = self.conn.recv(1024)
text = data.decode('utf-8')
if text.startswith("sig."):
exec(f"raise {text.split('.')[1]}")
elif data:
if text.startswith("HelloServer: "):
self.nick = text.replace("HelloServer: ","")
client = Client(self.conn,self.addr).registre(self.nick, "CONNECTED", False)
if client==False:
self.conn.send(b"sig.SystemExit(-5000,'The nick exists and is connected',True)")
else:
print(logFile().message(f"The host {self.nick} ({self.addr[0]}:{self.addr[1]}) is connected", True, "INFO"))
ListClients().add(self.conn)
else:
print(data)
在__init__()運行方法__listenData()中,該方法負責處理客戶端在服務器端發送的資料。
在__init__()我處理關閉客戶端時顯示資訊的例外。
try:
#{...}
finally:
try:
ListClients().remove(self.conn)
self.conn.close()
except:
None
finally:
Client(self.conn,self.addr).registre(self.nick,"DISCONNECTED",False)
#HERE, Can I close the current child process?
在此try執行a finally,因為總是會洗掉clients串列中的client,如果有連接就會關閉它。
問題
我的問題如下:
我運行服務器....

在客戶端機器上,我運行客戶端......

When I had connected the client at server, in the server process had created a child process.
Now the client closed, so in the server, if we show the child process his status changed to Z, is means, Zombie

My question, is...
How to close this child process? As the client is running in a child process started by multiprocessing.Process(). I must be close it with the method terminate() of multiprocessing... I think that is this the solution.
Solution possible?
I thought in...
- Add other child process listening a
multiprocessing.Event()in the root:
while sockSSL:
connection, address = sockSSL.accept()
eventChildStop = multiprocessing.Event()
subprocess = multiprocessing.Process(target=ClientListener, name="client", args=(connection, address,eventChildStop))
subprocess.start()
multiprocessing.Process(target=ClientListener.exitSubprocess, name="exitChildProcess",args=(eventChildStop, subprocess)).start()
time.sleep(1)
- In the class
listenerClientsI add the argumenteventin__init__():
class ClientListener:
def __init__(self,conn,addr,event):
- I add the static method
exitSubprocess(). This method in teory terminate the child process (this is not so):
@staticmethod
def exitSubprocess(event,process):
while True:
if event.is_set():
print(process.id)
process.terminate()
break
time.sleep(.5)
但是,事實并非如此,結果是一樣的。子行程(一個是方法 static exitSubprocess。第一個是客戶端行程)是 status Zombie。為什么...?

有人明白發生了什么嗎?
我很感激有人回應。感謝您的關注。
uj5u.com熱心網友回復:
解決方案
你好!!問題解決了!!
我該如何解決?
我這樣做是,在啟動客戶端的子行程之后,在父行程中啟動一個執行緒,當子行程退出時,退出之前,執行緒將子行程與父行程加入并且執行緒成功退出. 最后,客戶端的子行程退出。
要遵循的步驟
首先,在服務器的根代碼中添加:
# This thread is responsible of close the client's child process
threading.Thread(target=ClientListener.exitSubprocess,name="closeChildProcess",args=(eventChildStop,subprocess,)).start()
結果完成:
while sockSSL:
connection, address = sockSSL.accept()
eventChildStop = multiprocessing.Event()
subprocess = multiprocessing.Process(target=ClientListener, name="client", args=(connection, address,eventChildStop))
# This thread is responsible of close the client's child process
threading.Thread(target=ClientListener.exitSubprocess,name="closeChildProcess",args=(eventChildStop,subprocess,)).start()
subprocess.start()
time.sleep(1)
在新exitSubprocess方法之后,我改變了:
if event.is_set():
print(process.id)
process.terminate()
break
經過
if event.is_set():
process.join()
break
結果完成:
# This method get as argument the process child. For join it at parent process
@staticmethod
def exitSubprocess(event,process):
while True:
if event.is_set():
process.join()
break
time.sleep(.5)
重要的是,在客戶端的子行程中在他最后finally添加一個time.sleep(1)1 秒。給執行緒時間將客戶端的子行程加入父行程
class ClientListener:
def __init__(self,conn,addr,event):
try:
self.conn, self.addr = conn, addr
self.nick = ""
self.__listenData()
except (KeyboardInterrupt,SystemExit) as err:
print(logFile().message(f"The host {self.nick} ({self.addr[0]}:{self.addr[1]}) left", True, "INFO"))
except BaseException as err:
type, object, traceback = sys.exc_info()
file = traceback.tb_frame.f_code.co_filename
line = traceback.tb_lineno
print(logFile().message(f"{err} in {file}:{line}", True, "ERROR"))
finally:
try:
ListClients().remove(self.conn)
self.conn.close()
except:
None
finally:
Client(self.conn,self.addr).registre(self.nick,"DISCONNECTED",False)
event.set()
# This will delay 1 second to close the proccess, for this gives time at exitSubprocess method to join the client's child process with the parent process
time.sleep(1)
非常感謝您的關注和時間。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/377927.html
