Sono novizio con Python, sto cercando di costruire un piccolo demone che gestisca 5 socket contemporaneamente, e nel caso in cui tutti e cinque siano collegati, effettui un ping su ognuno di essi ogni trenta secondi, per liberarne uno appena possibile.
Codice server:
normalmente avvio questo daemon (dmn.py) import dmncodice:import threading, socket, time, sys from multiprocessing import Process local_address="localhost" class daemon(threading.Thread): socket_server = None socket_list = [[None, None], [None, None], [None, None], [None, None], [None, None]] socket_timeout = 30 pinged_socket = [False, False, False, False, False] pinger_process = [None, None, None, None, None] __local_port=None def __init__(self, local_port=24585, thread_id=1): threading.Thread.__init__(self) #self.daemon=True self.id=thread_id self.__local_port=local_port def run(self): try: # tentativo di inizializzazione del socket server che gestisce le connessioni self.socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket_server.bind((local_address, self.__local_port)) self.socket_server.listen(5) except socket.error as e: print("daemon couldn't open a socket server: "+str(e)) sys.exit(1) error_counter=0 count=0; try: # gestione delle connessioni: 1) accettazione; o se gia presente 2) ping while True: if self.socket_list[count] == [None, None]: self.socket_list[count][0], self.socket_list[count][1] = self.socket_server.accept() # 1) accettazione else: if not self.pinged_socket[count]: self.pinged_socket[count]=True print("set pinged_socket[",count,"] to ",self.pinged_socket[count]) self.pinger_process[count]=Process(target=self.PingSock, args=(count,)) # 2) ping ed eventuale chiusura self.pinger_process[count].start() if count==4: count=0 else: count+=1 except KeyboardInterrupt: # gestione dell'interruzione forzata da parte dell'utente del programma: chiusura sockets for i in range(len(self.socket_list)): if self.socket_list[i] != [None, None]: error_counter+=self.ShutdownAndCloseSock(i) sys.exit(error_counter) def ShutdownAndCloseSock(self, sock_num): # chiude un socket dell'oggetto daemon e ne azzera il wrapper (daemon.socket_list[]) return_value=0 try: self.socket_list[sock_num][0].shutdown(socket.SHUT_RDWR) except socket.error as e: print("daemon couldn't shut down socket n.%(sock_num)s: %(error_msg)s" %{"sock_num":sock_num, "error_msg":str(e)}) return_value+=1 finally: try: self.socket_list[sock_num][0].close() except socket.error as e: print("daemon couldn't close socket n.%(sock_num)s: %(error_msg)s" %{"sock_num":sock_num, "error_msg":str(e)}) return_value+=1 self.socket_list[sock_num] = [None, None] return return_value def KillDaemon(self): # chiude tutti gli eventuali socket aperti dal daemon e forza l'uscita errors=0 for i in range(len(self.socket_list)): if self.socket_list[i] != [None, None]: errors+=self.ShutdownAndCloseSock(i) exit(errors) def PingSock(self, socket_number): # processo adibito al ping di un socket di un oggetto daemon ed eventuale chiusura dello stesso closed_socket=0 self.socket_list[socket_number][0].settimeout(self.socket_timeout) try: self.socket_list[socket_number][0].send(b'ping') resp = self.socket_list[socket_number][0].recv(256) if resp!= b'pong' or resp==None: closed_socket+=self.ShutdownAndCloseSock(socket_number) print("closed sock ",socket_number," because not ponging: ",resp) else: self.socket_list[socket_number][0].settimeout(None) except socket.timeout: closed_socket+=self.ShutdownAndCloseSock(socket_number) print("closed sock ",socket_number," for timeout") self.pinged_socket[socket_number]=False print("set pinged_socket[",socket_number,"] to",self.pinged_socket[socket_number]) return closed_socket d=daemon() d.start()
e poi avvio il seguente client di prova che connette subito tutti e cinque i socket disponibili, poi però lascia che uno di essi decada per timeout non rispondendo "pong".
Codice client:
codice:import socket, time sock=[None, None, None, None, None] data=[None, None, None, None, None] for i in range(5): sock[i]=socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock[i].connect(("localhost",24585)) time.sleep(5) #def read(i): while True: for i in range(4): time.sleep(1) data[3-i]=sock[3-i].recv(1024) print(data[3-i]) if data[3-i]==b'ping': sock[3-i].send(b'pong') print("---------------") def KillAll(): for i in range(5): try: sock[i].shutdown(socket.SHUT_RDWR) sock[i].close() except socket.error: print("socket already closed: "+str(i)) exit(0)
Nella shell del server sembra funzionare tutto perfettamente, ma se dopo aver:
1) avviato il daemon
2) avviato il client
3) atteso la disconnessione del socket inattivo
cerco di leggere il valore di dmn.d.socket_list oppure di dmn.d.pinged_socket, ottengo valori totalmente inaspettati:
Output del demone
il socket risulta a tutti gli effetti chiuso, ma le funzioni della mia classe daemon non aggiornano le variabili pinged_socket e socket_listcodice:>>> import dmn >>> set pinged_socket[ 0 ] to True set pinged_socket[ 1 ] to True set pinged_socket[ 2 ] to True set pinged_socket[ 3 ] to True set pinged_socket[ 4 ] to True set pinged_socket[ 3 ] to False set pinged_socket[ 2 ] to False set pinged_socket[ 1 ] to False set pinged_socket[ 0 ] to False closed sock 4 for timeout set pinged_socket[ 4 ] to False >>> dmn.d.pinged_socket [True, True, True, True, True] <------------------ ?????????? >>> dmn.d.socket_list [[<socket.socket object, fd=3, family=2, type=1, proto=0>, ('127.0.0.1', 58151)], [<socket.socket object, fd=5, family=2, type=1, proto=0>, ('127.0.0.1', 58152)], [<socket.socket object, fd=6, family=2, type=1, proto=0>, ('127.0.0.1', 58153)], [<socket.socket object, fd=7, family=2, type=1, proto=0>, ('127.0.0.1', 58154)], [<socket.socket object, fd=8, family=2, type=1, proto=0>, ('127.0.0.1', 58155)]] >>> dmn.d.socket_list[4][0].send(b'hi') Traceback (most recent call ast): File "<stdin>", line 1, in <module> socket.error: [Errno 32] Broken pipe
cosa posso fare? darmi all'ippica?

Rispondi quotando