Author GeorgeY
Recipients GeorgeY, martin.panter
Date 2016-10-19.08:29:38
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1476865778.46.0.8446591567.issue28447@psf.upfronthosting.co.za>
In-reply-to
Content
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()

#<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:
                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 @ <socket.socket [closed] fd=-1, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0>

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: <socket.socket [closed] fd=-1, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0>
=================

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.
History
Date User Action Args
2016-10-19 08:29:38GeorgeYsetrecipients: + GeorgeY, martin.panter
2016-10-19 08:29:38GeorgeYsetmessageid: <1476865778.46.0.8446591567.issue28447@psf.upfronthosting.co.za>
2016-10-19 08:29:38GeorgeYlinkissue28447 messages
2016-10-19 08:29:38GeorgeYcreate