Domanda

Di recente ho visto un po 'di codice simile a questo (con calzino che è un oggetto socket ovviamente):

sock.shutdown(socket.SHUT_RDWR)
sock.close()

Qual è esattamente lo scopo di chiamare l'arresto sul socket e quindi chiuderlo? Se fa la differenza, questo socket viene utilizzato per IO non bloccanti.

È stato utile?

Soluzione

Eccone uno spiegazione :

  

Quando non è più necessario un socket,   il programma chiamante può scartare il   socket applicando una subroutine di chiusura   al descrittore di socket. Se una   presa di consegna affidabile ha dati   associato ad esso quando si chiude   posto, il sistema continua a tentare   trasferimento dati. Tuttavia, se i dati lo sono   ancora non consegnato, il sistema scarta   i dati. Dovrebbe l'applicazione   il programma non ha alcuna utilità per qualsiasi in sospeso   dati, può utilizzare l'arresto   subroutine sul socket prima di   chiudendolo.

Altri suggerimenti

La chiamata di close e shutdown ha due effetti diversi sul socket sottostante.

La prima cosa da sottolineare è che il socket è una risorsa nel sistema operativo sottostante e più processi possono avere un handle per lo stesso socket sottostante.

Quando si chiama close diminuisce il conteggio degli handle di uno e se il conteggio degli handle ha raggiunto lo zero, il socket e la connessione associata passano attraverso la normale procedura di chiusura (inviando effettivamente un FIN / EOF al peer) e il socket è deallocato.

La cosa a cui prestare attenzione qui è che se il conteggio degli handle non raggiunge lo zero perché un altro processo ha ancora un handle per il socket, la connessione non viene chiusa e il socket non viene deallocato.

D'altra parte, chiamando shutdown per leggere e scrivere si chiude la connessione sottostante e si invia un FIN / EOF al peer indipendentemente da quanti processi hanno handle per il socket. Tuttavia, non disloca il socket e dovrai comunque chiamare in seguito.

Spiegazione di arresto e chiusura: Arresto grazioso (msdn)

L'arresto (nel tuo caso) indica all'altra estremità della connessione che non vi è alcuna ulteriore intenzione di leggere o scrivere sul socket. Quindi close libera tutta la memoria associata al socket.

Se si omette l'arresto, il socket potrebbe rimanere nello stack del sistema operativo fino a quando la connessione non verrà chiusa correttamente.

IMO i nomi 'shutdown' e 'close' sono fuorvianti, 'close' e 'destro' enfatizzerebbero le loro differenze.

è menzionato proprio nel Socket Programming HOWTO ( py2 / < a href = "http://docs.python.org/3/howto/sockets.html#disconnecting" rel = "noreferrer"> py3 )

  

scollegamento

     

In senso stretto, dovresti utilizzare shutdown su un socket prima di chiudere .   Il shutdown è un avviso al socket all'altro capo. A seconda dell'argomento che lo passi, può significare & # 8220; Non invierò più, ma ascolterò ancora & # 8217; ascolterò ancora & # 8221; oppure & # 8220 ; Non sto ascoltando, buon viaggio! & # 8221 ;.   La maggior parte delle librerie di socket, tuttavia, sono così usate dai programmatori che trascurano di usare questa etichetta che normalmente un close è lo stesso di shutdown (); close () .   Pertanto, nella maggior parte dei casi, non è necessario un arresto esplicito.

     

...

Questo codice sopra non è sbagliato?

La chiamata di chiusura direttamente dopo la chiamata di arresto potrebbe far sì che il kernel scarti comunque tutti i buffer in uscita.

Secondo http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable è necessario attendere tra l'arresto e la chiusura fino a quando la lettura non restituisce 0.

Shutdown (1), impone al socket no di inviare ulteriori dati

Questo è utile in

1- Svuotamento buffer

2- Rilevamento di errori strani

3- Protezione sicura

Lasciami spiegare di più, quando invii un dato da A a B, non è garantito che lo sia inviato a B, è garantito solo per essere inviato al buffer A os, che a sua volta lo invia al buffer di sistema operativo

Quindi chiamando shutdown (1) su A, si cancella il buffer di A e viene generato un errore se il buffer non è vuoto, ovvero: i dati non sono stati ancora inviati al peer

Tuttavia, questo è irreversibile, quindi puoi farlo dopo tutto ha inviato tutti i tuoi dati e vuoi essere sicuro che siano almeno pari buffer os

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top