[issue28447] socket.getpeername() failure on broken TCP/IP connection
Georgey added the comment: Not only does the getpeername() method not work, but the socket instance itself has been destroyed as garbage by python. - I understand the former, but cannot accept the latter. -- resolution: not a bug -> wont fix status: closed -> pending ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue28447> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28447] socket.getpeername() failure on broken TCP/IP connection
Georgey added the comment: Hello David, Yes I had the same thought with you that the information of socket is lost at operating syetem level. However, I hope at Python level this kind of information will not be lost. Once the socket has been created by incoming connection, the address information of 'laddr' and 'raddr' has been known, and print(socket) will show them. It is not necessarily lost when the connection is broken. Any static method, like assigning an attribute of address to the socket will help. To the the least, Python shall not automatically destroy the socket object simply because it has been closed by Windows. Otherwise any attempt to record the address information of the socket will fail after it is destoyed. The error shown in message 278968 has clearly shown that even as a key, the socket object cannot function because it is already destroyed. -- sock_err @ Exception in thread Thread-1: Traceback (most recent call last): File "C:/Users/user/Desktop/SelectWinServer.py", line 39, in handle_sock_err addr_del = sock.getpeername() OSError: [WinError 10038] During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Python34\lib\threading.py", line 911, in _bootstrap_inner self.run() File "C:/Users/user/Desktop/SelectWinServer.py", line 67, in run handle_sock_err(msg[1]) File "C:/Users/user/Desktop/SelectWinServer.py", line 41, in handle_sock_err addr_del = socks2addr[sock] KeyError: = -- resolution: not a bug -> remind status: closed -> open ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue28447> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28447] socket.getpeername() failure on broken TCP/IP connection
Georgey added the comment: The socket close accident is not caused by queue or calling handle_sock_error at all, it happened right after select error After changing the Exception handling of main Thread: except Exception as err: print("error:"+str(err)) print(sock.getpeername()) mailbox.put( (("sock_err",sock), 'Server') ) continue server_sock.close() I also get the same type of error: Traceback (most recent call last): File "C:\Users\user\Desktop\SelectWinServer.py", line 112, in data = sock.recv(BUFSIZ) ConnectionResetError: [WinError 10054] connection forcibly close During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Users\user\Desktop\SelectWinServer.py", line 123, in print(sock.getpeername()) OSError: [WinError 10038] not a socket -- ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue28447> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28447] socket.getpeername() failure on broken TCP/IP connection
Georgey added the comment: I have changed the code to report any error that occurs in receiving message, and it reports: [WinError10054] An existing connection was forcibly closed by the remote host Well, this error is the one we need to handle, right? A server need to deal with abrupt offlines of clients. Yes the romote host has dropped and connection has been broken, but that does not mean we cannot recall its address. If this is not a bug, I don't know what is a bug in socket module. -- import socket import select, time import queue, threading ISOTIMEFORMAT = '%Y-%m-%d %X' BUFSIZ = 2048 TIMEOUT = 10 ADDR = ('', 15625) SEG = "◎◎" SEG_ = SEG.encode() active_socks = [] socks2addr = {} server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_sock.bind(ADDR) server_sock.listen(10) active_socks.append(server_sock) mailbox = queue.Queue() # def send(mail): mail_ = SEG_+ mail.encode() ##The SEG_ at the beginning can seperate messeges for recepient when internet busy for sock in active_socks[1:]: try: sock.send(mail_) except: handle_sock_err(sock) def handle_sock_err(sock): try: addr_del = sock.getpeername() except: addr_del = socks2addr[sock] active_socks.remove(sock) socks2addr.pop(sock) sock.close() send("OFFLIN"+str(addr_del) ) # class Sender(threading.Thread): #process 'mails' - save and send def __init__(self, mailbox): super().__init__() self.queue = mailbox def analyze(self, mail, fromwhere): send( ' : '.join((fromwhere, mail)) ) def run(self): while True: msg, addr = mailbox.get() ### if msg[0] =="sock_err": print("sock_err @ ", msg[1]) #alternative> print("sock_err @ " + repr( msg[1] ) ) #the alternaive command greatly reduces socket closing handle_sock_err(msg[1]) continue self.analyze(msg, addr) sender = Sender(mailbox) sender.daemon = True sender.start() # while True: onlines = list(socks2addr.values()) print( '\n'+time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) ) print( 'online: '+str(onlines)) read_sockets, write_sockets, error_sockets = select.select(active_socks,[],[],TIMEOUT) for sock in read_sockets: #New connection if sock ==server_sock: # New Client coming in clisock, addr = server_sock.accept() ip = addr[0] active_socks.append(clisock) socks2addr[clisock] = addr #Some incoming message from a client else: # Data recieved from client, process it try: data = sock.recv(BUFSIZ) if data: fromwhere = sock.getpeername() mail_s = data.split(SEG_) ##seperate messages del mail_s[0] for mail_ in mail_s: mail = mail_.decode() print("recv>"+ mail) except Exception as err: print( "SOCKET ERROR: "+str(err) ) mailbox.put( (("sock_err",sock), 'Server') ) continue server_sock.close() == -- resolution: not a bug -> wont fix status: closed -> open ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue28447> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28447] socket.getpeername() failure on broken TCP/IP connection
Georgey added the comment: so when do you think the error socket closes? -- ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue28447> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28447] socket.getpeername() failure on broken TCP/IP connection
Georgey added the comment: As your request, I simplify the server here: -- import socket import select, time import queue, threading ISOTIMEFORMAT = '%Y-%m-%d %X' BUFSIZ = 2048 TIMEOUT = 10 ADDR = ('', 15625) SEG = "◎◎" SEG_ = SEG.encode() active_socks = [] socks2addr = {} server_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_sock.bind(ADDR) server_sock.listen(10) active_socks.append(server_sock) mailbox = queue.Queue() # def send(mail): mail_ = SEG_+ mail.encode() ##The SEG_ at the beginning can seperate messeges for recepient when internet busy for sock in active_socks[1:]: try: sock.send(mail_) except: handle_sock_err(sock) def handle_sock_err(sock): try: addr_del = sock.getpeername() except: addr_del = socks2addr[sock] active_socks.remove(sock) socks2addr.pop(sock) sock.close() send("OFFLIN"+str(addr_del) ) # class Sender(threading.Thread): #process 'mails' - save and send def __init__(self, mailbox): super().__init__() self.queue = mailbox def analyze(self, mail, fromwhere): send( ' : '.join((fromwhere, mail)) ) def run(self): while True: msg, addr = mailbox.get() ### if msg[0] =="sock_err": print("sock_err @ ", msg[1]) #alternative> print("sock_err @ " + repr( msg[1] ) ) #the alternaive command greatly reduces socket closing handle_sock_err(msg[1]) continue self.analyze(msg, addr) sender = Sender(mailbox) sender.daemon = True sender.start() # while True: onlines = list(socks2addr.values()) print( '\n'+time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) ) print( 'online: '+str(onlines)) read_sockets, write_sockets, error_sockets = select.select(active_socks,[],[],TIMEOUT) for sock in read_sockets: #New connection if sock ==server_sock: # New Client coming in clisock, addr = server_sock.accept() ip = addr[0] active_socks.append(clisock) socks2addr[clisock] = addr #Some incoming message from a client else: # Data recieved from client, process it try: data = sock.recv(BUFSIZ) if data: fromwhere = sock.getpeername() mail_s = data.split(SEG_) ##seperate messages del mail_s[0] for mail_ in mail_s: mail = mail_.decode() print("recv>"+ mail) except: mailbox.put( (("sock_err",sock), 'Server') ) continue server_sock.close() == The client side can be anything that tries to connect the server. The original server has a bulletin function that basically echoes every message from any client to all clients. But you can ignore this function and limit the client from just connecting to this server and do nothing before close. I find the error again: -- sock_err @ Exception in thread Thread-1: Traceback (most recent call last): File "C:/Users/user/Desktop/SelectWinServer.py", line 39, in handle_sock_err addr_del = sock.getpeername() OSError: [WinError 10038] During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Python34\lib\threading.py", line 911, in _bootstrap_inner self.run() File "C:/Users/user/Desktop/SelectWinServer.py", line 67, in run handle_sock_err(msg[1]) File "C:/Users/user/Desktop/SelectWinServer.py", line 41, in handle_sock_err addr_del = socks2addr[sock] KeyError: = It seems that "socks2addr" has little help when socket is closed and "getpeername()" fails - it will fail too. However, I do find that altering print("sock_err @ ", msg[1]) to print("sock_err @ " + repr( msg[1] ) ) can reduce socket closing. Don't understand why and how important it is. BTW, on Windows 7 or Windows 10. -- ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue28447> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28447] socket.getpeername() failure on broken TCP/IP connection
Georgey added the comment: Yes that is definitely a closed socket. But it is strange that in a single thread server without select module, the socket is never closed until I explicitly use close() method. except: print(sock) #<- here it looks normal time.sleep(3) print(sock) #<- here it still looks normal sock.close() print(sock) #<- finally the [closed] tag appears and all the details lost So I guess the "Socket Automatically Closing" effect associate with "select" module? For when I run the single-thread server in the IDLE and called time.sleep(), it has been already treated as multi-thread. -- ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue28447> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28447] socket.getpeername() failure on broken TCP/IP connection
Georgey added the comment: "Without code or something demonstrating the bug, I’m pretty sure it is a bug in your program" Here is the main Thread --- mailbox = queue.Queue() while True: #print(addr_groups) unknown_clients=[] for key in yellow_page.keys(): if yellow_page[key][0] ==None: unknown_clients.append(key) print("\n", name_groups) if len(unknown_clients) >0: print("unknown from:"+str(unknown_clients)) print(time.strftime(ISOTIMEFORMAT, time.localtime(time.time())) + '\n') # Get the list sockets which are ready to be read through select read_sockets, write_sockets, error_sockets = select.select(active_socks,[],[],TIMEOUT) for sock in read_sockets: #New connection if sock ==server_sock: # New Client coming in clisock, addr = server_sock.accept() ip = addr[0] if ip in IPALLOWED: active_socks.append(clisock) yellow_page[addr] = [None,None,clisock] else: clisock.close() #Some incoming message from a client else: # Data recieved from client, process it try: data = sock.recv(BUFSIZ) if data: fromwhere = sock.getpeername() mail_s = data.split(SEG_) del mail_s[0] for mail_ in mail_s: mail = mail_.decode() except: mailbox.put( (("sock_err",sock), 'localhost') ) continue = so the sub thread's job is to analyze the exception put into "mailbox" Here is the run function of sub thread --- def run(self): while True: msg, addr = mailbox.get() if msg[0] =="sock_err": print("sock_err @ ", msg[1]) #<< remind status: closed -> open ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue28447> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue28447] socket.getpeername() failure on broken TCP/IP connection
Georgey added the comment: I have changed my Username, thanks martin. " But it sounds like you may be closing the socket in one thread, and trying to use it in another thread" -- I do not attempt to "close" it in main thread. Main only detect the connection failure and report the socket object to the sub thread. sub thread tries to identify the socket object (retrieve the IP address) before closing it. The question is - once the TCP connection is broken (e.g. client's program get a crash), how can I get to know the original address of that connection? It seems like once someone(socket) dies, I am not allowed to know the name(address)! -- nosy: +GeorgeY resolution: not a bug -> remind ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue28447> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com