Python: Avsluta socket anslutning snyggt? (Nu med fråga 2)

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
JimmyAndersson
Inlägg: 26544
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Python: Avsluta socket anslutning snyggt? (Nu med fråga 2)

Inlägg av JimmyAndersson »

Jo det är jag igen. :D
OS: Windows XP och Python 2.7.6 även denna gång.

Jag använder "socket" för att skapa en anslutning mellan en server och en klient.
Kring detta funderar jag på två saker, men jag tar en sak i taget:


Om klienten plötsligt avbryter anslutningen. T.ex om programmet kraschar
eller om CTRL+C abrupt bara avslutar programmet utan att stänga innan.
Hur hanterar man detta snyggt i servern?



Koden för att ta emot data ser ut såhär:

Kod: Markera allt

        try:
            data = clientsocket.recv(1024)
            data = data.decode('iso8859-1')
            data_ren = data.rstrip() #Tar bort alla former av 'newline' och 'whitespace'
        except KeyboardInterrupt:
osv..
("KeyboardInterrupt" är bara för att fånga när man trycker CTRL+C i fönstret som kör server-scriptet.
Det har inget med detta problem att göra.)



Och så här ser det ut hos servern när jag avbryter klient-scriptet med CTRL+BREAK :

Unhandled exception in thread started by <function handler at 0x00BAC9B0>
Traceback (most recent call last):
File "server2.py", line 23, in handler
data = clientsocket.recv(1024)
socket.error: [Errno 10054] En befintlig anslutning tvingades att stõnga av fjärrvärddatorn



Jag tolkade det som att exception-typen är "socket.error" och justerade exception-raden såhär:

Kod: Markera allt

        try:
            data = clientsocket.recv(1024)
            data = data.decode('iso8859-1')
            data_ren = data.rstrip() #Tar bort alla former av 'newline' och 'whitespace'
        except clientsocket.error:
osv..

Men då ser det ut så här hos servern när jag avbryter klient-scriptet med CTRL+BREAK :

"Unhandled exception in thread started by <function handler at 0x00BAC9B0>
Traceback (most recent call last):
File "server2.py", line 26, in handler
except clientsocket.error:
AttributeError: '_socketobject' object has no attribute 'error'"



Jag har letat efter andra lösningar och funnit bl.a:

except socket.error, (value,message):
Länk

Men det gav samma fel.

Jag vill främst alltså "läsa av" ifall anslutningen brutits av t.ex klienten.
(Och som steg två även ta hand om CTRL+C hos servern.
Det vore smidigt om det gick att få med i samma exception.)




-----
Som parentes kan jag nämna fråga nr 2 också:

Naturligtvis vill man ju inte behöva stänga anslutningen med CTRL+C eller liknande.
Man vill ju ha ett val för "stäng anslutning". :)
Så hur stänger man anslutningen snyggt?
sodjan
EF Sponsor
Inlägg: 43247
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Python: Avsluta socket anslutning snyggt?

Inlägg av sodjan »

> Så hur stänger man anslutningen snyggt?

Servern måste ju veta att clienten vill stänga.
Du kan skicka något till servern, "--EXIT--" eller
liknande som du kan testa för.

På första frågan passar jag... :-)
xxargs
Inlägg: 10189
Blev medlem: 23 september 2006, 14:28:27
Ort: Södertälje

Re: Python: Avsluta socket anslutning snyggt?

Inlägg av xxargs »

Är det inte därför man har time to live och heart-beat eller liknande mekanismer.

dvs. har det inte varit aktivitet på socket tillräckligt länge så antas att klienten har dött på oförutsett sätt och därför hugger ned kopplingen på serversidan - annars är risken stor att det lagras upp hängande kopplingar i oändlighet och man slår i taket minnesmässigt etc. .

Överlastningsattacker etc. nyttjar det här med all lämna öppnade kopplingar och skapa nya hela tiden för att försöka få hål i systemet och/eller kväsa tillgängliga resurser (som max. antal kopplingar samtidigt) och det här är inget enkelt problem att hantera då man inte får minsta hint i från klienten att den har dött och kan bara gå på trafiken och när den pratade sist.
Användarvisningsbild
JimmyAndersson
Inlägg: 26544
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: Python: Avsluta socket anslutning snyggt?

Inlägg av JimmyAndersson »

Så sant, men jag vill även kunna ta hand om avbrott som görs innan timeout-tiden
för att slippa få ett felmeddelande från Python.
T.ex nu när jag testar detta så startar jag först server-scriptet och sedan client-scriptet.
Direkt därefter trycker jag CTRL + BREAK i klient-fönstret.



Men nu har jag faktiskt löst det. :)

Titta på den här raden:

from socket import *

Den är faktiskt orsaken till varför jag får "AttributeError: '_socketobject' object has no attribute 'error'""


Hade jag haft:
import socket

så hade jag behövt specificera, dvs: socket.socket()
men med from socket import * så räcker det med socket()

Jag insåg att det är samma sak med socket.error,
så det blir bara error.
Därför fick jag felmeddelandet om AttributeError. :)

Så detta är som sagt löst.


Jag återkommer med fråga 2.
Användarvisningsbild
JimmyAndersson
Inlägg: 26544
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: Python: Avsluta socket anslutning snyggt?

Inlägg av JimmyAndersson »

Och här har vi fråga 2:
"Så hur stänger man anslutningen snyggt?"

Sodjan:
'Servern måste ju veta att clienten vill stänga.
Du kan skicka något till servern, "--EXIT--" eller
liknande som du kan testa för.'


Så långt är det inga problem. Jag använder "-q" i nuläget.
Den del av server-scriptet som hanterar detta:

Kod: Markera allt

            elif data == '-q':
                print("Okej, vi avslutar.")
                clientsocket.close()
                run = False
                print("Avslutat.")
                exit()
Men trots att jag har med exit() så avslutas inte scriptet.
Jag ser:
Okej, vi avslutar.
Avslutat.


Ingen markör eller prompt efter detta, så jag måste avbryta med CTRL-C.
Det får mig att misstänka att det inte räcker med clientsocket.close()



Här är hela serverscriptet som det ser ut i nuläget:

Kod: Markera allt

#!/usr/bin/python
# -*- coding: iso8859-1 -*-
from socket import *
import thread
import sys
import traceback

data = ""
run = True

def handler(clientsocket, clientaddr):
    print"Server accepted connection from: ", clientaddr
    
    global data
    global run

    
    while run == True:
        try:
            data = clientsocket.recv(1024)
            data = data.rstrip()    #Tar bort alla former av 'newline' och 'whitespace'
            
            if not data:
                pass
            elif data == '-q':
                print("Okej, vi avslutar.")
                clientsocket.close()
                run = False
                print("Avslutat.")
                exit()
            elif data != '':
                print "Servern tog emot: ", data
                msg = "Servern tog emot: %s" % data #Skickar tillbaka till klienten
                clientsocket.send(msg)
                clientsocket.send('\n\r')
                #clientsocket.send('-q')
                
        except error, (value,message):
            #clientsocket.close()  #Behövs den?
            run = False
            lokal_text = "Anslutningen avbröts."
            print(lokal_text.decode('iso8859-1')) #För att få rätt åäö i cmd-fönstret.
            #break
            exit()



if __name__ == "__main__":
    host = '127.0.0.1'
    port = 23
    buf = 1024
        
    addr = (host, port)
     
    serversocket = socket(AF_INET, SOCK_STREAM)
     
    serversocket.bind(addr)
     
    serversocket.listen(2)
 
    while 1:
        print("Server is listening for connections\n")
        clientsocket, clientaddr = serversocket.accept()
        thread.start_new_thread(handler, (clientsocket, clientaddr))

    clientsocket.close()
    print("Hamnar vi här")

exit()

Gör jag rätt när jag bara stänger clientsocket?
Jag har läst om shutdown() men inte riktigt fått det att fungera.

Om jag har med clientsocket.shutdown(socket.SHUT_RDWR) före raden clientsocket.close()
så får jag detta när jag ska avsluta:

Kod: Markera allt

Okej, vi avslutar.
Unhandled exception in thread started by <function handler at 0x00BAC9B0>
Traceback (most recent call last):
  File "numpres_server2.py", line 27, in handler
    clientsocket.shutdown(socket.SHUT_RDWR)
AttributeError: type object '_socketobject' has no attribute 'SHUT_RDWR'

Jag har läst bl.a här:
http://stackoverflow.com/questions/4097 ... cket-close
http://msdn.microsoft.com/en-us/library ... 85%29.aspx

Men det är lite för massivt för en nybörjare, så jag lyckas inte riktigt bena ut vad jag missar.
Användarvisningsbild
JimmyAndersson
Inlägg: 26544
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: Python: Avsluta socket anslutning snyggt? (Nu med fråga

Inlägg av JimmyAndersson »

En tanke:
Kan det var så att jag tittar på fel ställe?
Att scriptet inte avslutas ordentligt kanske har med trådningen att göra?

Någon som vet hur trådar påverkas av att man kör exit() i huvudtråden?

Två av alla sidor där jag försökt hitta svaret:
http://docs.python.org/2/library/except ... SystemExit
http://docs.python.org/2/library/thread.html
Pajn
Inlägg: 1160
Blev medlem: 6 juni 2008, 19:14:29
Ort: Nyköping
Kontakt:

Re: Python: Avsluta socket anslutning snyggt? (Nu med fråga

Inlägg av Pajn »

Nu är jag lite tråkig, men jag tror att du får bättre svar om du läser här än om jag försöker skriva ihop nått
http://stackoverflow.com/questions/1489 ... hon-thread

>Någon som vet hur trådar påverkas av att man kör exit() i huvudtråden?
För att det ska funka som du (antagligen) förväntar dig måste alla trådar flaggas som demoner:
http://stackoverflow.com/questions/4330 ... n-property
Användarvisningsbild
JimmyAndersson
Inlägg: 26544
Blev medlem: 6 augusti 2005, 21:23:33
Ort: Oskarshamn (En bit utanför)
Kontakt:

Re: Python: Avsluta socket anslutning snyggt? (Nu med fråga

Inlägg av JimmyAndersson »

Ingen fara. All hjälp är bra hjälp. :)

Jag börjar förstå lite mer nu.
Bl.a att min trådhantering i scriptet är väldigt ..spartansk, för att försöka använda ett fint ord.
Det saknas lite grejer och den är ganska ostrukturerad.

Dessutom (om jag fattat rätt) så är det mycket smidigare med threading.Thread
jämfört med thread, så jag ska göra ett testscript med det istället.


Till frukosten läste jag den här sidan. (Jo, den sista skvätten kaffe var iskall när jag nått slutet på sidan.)
http://inventwithpython.com/blog/2013/0 ... readworms/
Det är *så* guider ska vara skrivna för att jag ska trivas bäst. :)


Så nu verkar det som att jag har lite att pyssla med igen. Kul!



edit:
Jajjamensan, visst var det pga oavslutade trådar som scriptet fastnade. :)
Skriv svar