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()

#<helper functions>

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) )

#<sub Thread>
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()

#<main Thread>
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

Reply via email to