Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

socket.close socket.shutdown merdouille

23 réponses
Avatar
chris
Bonjour,

comment on ferme correctement une socket ?

je fais bien un socket.shutdown(1)
puis un socket.close()

le tout correctement
les thread se termine tout seul ...

et quand j'arrete le tout probleme avec bind tout de suite apres

j'ai essayé de tout lire sur google mais bon
ya un truc qui m'echappe

bon les clients c'est des telnet qui sont fermés coté serveur
le probleme viendrait t il de la ?

Merci pour vos remarque

A+
chris

10 réponses

1 2 3
Avatar
Christophe Cavalaria
chris wrote:

Bonjour,

comment on ferme correctement une socket ?

je fais bien un socket.shutdown(1)
puis un socket.close()

le tout correctement
les thread se termine tout seul ...

et quand j'arrete le tout probleme avec bind tout de suite apres

j'ai essayé de tout lire sur google mais bon
ya un truc qui m'echappe

bon les clients c'est des telnet qui sont fermés coté serveur
le probleme viendrait t il de la ?

Merci pour vos remarque


Quand tu ouvres ton socket, du coté server tu imposes je suppose d'utiliser
un port précis. C'est pratique cela permet au client de retrouver ton
serveur en connaissant seulement l'IP. Quand le client ou le serveur veut
fermer la connection, le protocole réseau envoit un packet pour prévenir et
attend une réponse de l'autre coté pour dire que le packet à bien été reçu,
et si cette réponse d'arrive pas, il en renvoit un autre.

Du coup, si tu fermes ton socket un peu trop barbarement, en général en
quittant le client ou le serveur immédiatement après, la communication
entre le client et le serveur ne se fait pas toujours correctement et l'OS
peut souvent garder le socket encore actif le temps de finir la
communication, même si le processus qui l'a ouvert n'est plus vivant.

La solution est simple : crée ton socket sur le serveur avec le flag
autorisant une autre application à réouvrir le port, même si celui-ci est
déjà utilisé.

Par exemple, voici comment la classe SocketServer de la lib standard fait
ça :

if self.allow_reuse_address:
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(self.server_address)

C'est considéré comme une possible faille de sécurité je crois mais ça ne
pose probablement aucun problème en developement.

Attention, si ton client spécifie aussi le port à utiliser en local, cela ne
marchera pas bien !

Plus d'infos sans doute mieux expliqué que moi, mais en anglais et pas
spécifique au Python : http://hea-www.harvard.edu/~fine/Tech/addrinuse.html

Avatar
chris


As-tu des try: except: dans tes threads clients ?

Puisque tu les plante depuis ta tache principale, ils risquent de ne pas
aimer.

... je te conseille d'utiliser join.

hg

ok on va essayer

Merci
A+

Avatar
chris
re bonjour,

et non même pas en fait chaque thread est une boucle
while self.running:

un shutdown met a False cette variabel
et tout mes threads se termine tout seul
en sortie de boucle et ils ferment leur connexion

mais dans cas ais je besoin d'un join()

je ne croyais pas ou alors qq chose m'echappe

A+
chris
Avatar
chris
Merci
beaucoup cela fonctionne

A+
chris
Avatar
hg
Christophe Cavalaria wrote:

chris wrote:

Bonjour,

comment on ferme correctement une socket ?

je fais bien un socket.shutdown(1)
puis un socket.close()

le tout correctement
les thread se termine tout seul ...

et quand j'arrete le tout probleme avec bind tout de suite apres

j'ai essayé de tout lire sur google mais bon
ya un truc qui m'echappe

bon les clients c'est des telnet qui sont fermés coté serveur
le probleme viendrait t il de la ?

Merci pour vos remarque


Quand tu ouvres ton socket, du coté server tu imposes je suppose
d'utiliser un port précis. C'est pratique cela permet au client de
retrouver ton serveur en connaissant seulement l'IP. Quand le client ou le
serveur veut fermer la connection, le protocole réseau envoit un packet
pour prévenir et attend une réponse de l'autre coté pour dire que le
packet à bien été reçu, et si cette réponse d'arrive pas, il en renvoit un
autre.

Du coup, si tu fermes ton socket un peu trop barbarement, en général en
quittant le client ou le serveur immédiatement après, la communication
entre le client et le serveur ne se fait pas toujours correctement et l'OS
peut souvent garder le socket encore actif le temps de finir la
communication, même si le processus qui l'a ouvert n'est plus vivant.

La solution est simple : crée ton socket sur le serveur avec le flag
autorisant une autre application à réouvrir le port, même si celui-ci est
déjà utilisé.

Par exemple, voici comment la classe SocketServer de la lib standard fait
ça :

if self.allow_reuse_address:
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind(self.server_address)

C'est considéré comme une possible faille de sécurité je crois mais ça ne
pose probablement aucun problème en developement.

Attention, si ton client spécifie aussi le port à utiliser en local, cela
ne marchera pas bien !

Plus d'infos sans doute mieux expliqué que moi, mais en anglais et pas
spécifique au Python :
http://hea-www.harvard.edu/~fine/Tech/addrinuse.html



C'est effectivement une faille, mais surtout, ça risque de créer d'autres
effets de bords dans son appli/cacher des bugs liés aux "fermeture
barbare ... " ... enfin c'est mon avis.

hg


Avatar
Christophe Cavalaria
hg wrote:

Christophe Cavalaria wrote:
Plus d'infos sans doute mieux expliqué que moi, mais en anglais et pas
spécifique au Python :
http://hea-www.harvard.edu/~fine/Tech/addrinuse.html



C'est effectivement une faille, mais surtout, ça risque de créer d'autres
effets de bords dans son appli/cacher des bugs liés aux "fermeture
barbare ... " ... enfin c'est mon avis.


Enfin, un des problèmes c'est que ce cas peut arriver même en
procédure "normale". Il suffit que le client plante ou que le serveur perde
la connexion avec le client et c'est fini. Ou alors, il suffit tout
simplement que ce soit le serveur qui ferme le socket en premier et le
risque est la. Dans ces cas, même avec une programmation rigoureuse, le
problème ressurgira. Dans tous les cas, la faille de sécurité est vraiment
mineure et bien souvent négligeable. L'attaquant doit avoir un compte actif
sur la machine serveur pour pouvoir en profiter.

Ici, j'entend par serveur le programme qui à ouvert le socket en écoute.


Avatar
hg
Christophe Cavalaria wrote:

hg wrote:

Christophe Cavalaria wrote:
Plus d'infos sans doute mieux expliqué que moi, mais en anglais et pas
spécifique au Python :
http://hea-www.harvard.edu/~fine/Tech/addrinuse.html



C'est effectivement une faille, mais surtout, ça risque de créer d'autres
effets de bords dans son appli/cacher des bugs liés aux "fermeture
barbare ... " ... enfin c'est mon avis.


Enfin, un des problèmes c'est que ce cas peut arriver même en
procédure "normale". Il suffit que le client plante ou que le serveur
perde la connexion avec le client et c'est fini. Ou alors, il suffit tout
simplement que ce soit le serveur qui ferme le socket en premier et le
risque est la. Dans ces cas, même avec une programmation rigoureuse, le
problème ressurgira. Dans tous les cas, la faille de sécurité est vraiment
mineure et bien souvent négligeable. L'attaquant doit avoir un compte
actif sur la machine serveur pour pouvoir en profiter.

Ici, j'entend par serveur le programme qui à ouvert le socket en écoute.



Si le run de chaque thread d'écoute du serveur est sous try: except: alors
chaque thread retournera toujours proprement, même si le/les clients se
plantent ... et alors le join aboutira correctement dans tous les cas de
figures.

Tu es d'accord ?

hg



Avatar
Christophe Cavalaria
hg wrote:

Christophe Cavalaria wrote:

hg wrote:

Christophe Cavalaria wrote:
Plus d'infos sans doute mieux expliqué que moi, mais en anglais et pas
spécifique au Python :
http://hea-www.harvard.edu/~fine/Tech/addrinuse.html



C'est effectivement une faille, mais surtout, ça risque de créer
d'autres effets de bords dans son appli/cacher des bugs liés aux
"fermeture barbare ... " ... enfin c'est mon avis.


Enfin, un des problèmes c'est que ce cas peut arriver même en
procédure "normale". Il suffit que le client plante ou que le serveur
perde la connexion avec le client et c'est fini. Ou alors, il suffit tout
simplement que ce soit le serveur qui ferme le socket en premier et le
risque est la. Dans ces cas, même avec une programmation rigoureuse, le
problème ressurgira. Dans tous les cas, la faille de sécurité est
vraiment mineure et bien souvent négligeable. L'attaquant doit avoir un
compte actif sur la machine serveur pour pouvoir en profiter.

Ici, j'entend par serveur le programme qui à ouvert le socket en écoute.



Si le run de chaque thread d'écoute du serveur est sous try: except: alors
chaque thread retournera toujours proprement, même si le/les clients se
plantent ... et alors le join aboutira correctement dans tous les cas de
figures.

Tu es d'accord ?


Je dois dire que j'ai pas suivi votre histoire de thread. Et en y regardant
de plus pret, je pense que le problème n'est absolument pas lié aux
threads. En fait, il n'existe pas de façon barbare de fermer un socket. Le
problème des TIME_WAIT viens soit d'une coupure brusque de la connection
réseau (machine distante qui plante ou connection entre les deux machines
subitement impossible), soit du fait qu'après un close, rien ne garantit
que tu puisses immédiatement faire un bind sur le même port.

En effet, close termine immédiatement puis c'est à l'OS de s'occuper de
finir de fermer la socket ce qui prend du temps. Essayer de l'ouvrir
immédiatement après un close n'est donc absolument pas garantit de
fonctionner.




Avatar
hg
Christophe Cavalaria wrote:

hg wrote:

Christophe Cavalaria wrote:

hg wrote:

Christophe Cavalaria wrote:
Plus d'infos sans doute mieux expliqué que moi, mais en anglais et pas
spécifique au Python :
http://hea-www.harvard.edu/~fine/Tech/addrinuse.html



C'est effectivement une faille, mais surtout, ça risque de créer
d'autres effets de bords dans son appli/cacher des bugs liés aux
"fermeture barbare ... " ... enfin c'est mon avis.


Enfin, un des problèmes c'est que ce cas peut arriver même en
procédure "normale". Il suffit que le client plante ou que le serveur
perde la connexion avec le client et c'est fini. Ou alors, il suffit
tout simplement que ce soit le serveur qui ferme le socket en premier et
le risque est la. Dans ces cas, même avec une programmation rigoureuse,
le problème ressurgira. Dans tous les cas, la faille de sécurité est
vraiment mineure et bien souvent négligeable. L'attaquant doit avoir un
compte actif sur la machine serveur pour pouvoir en profiter.

Ici, j'entend par serveur le programme qui à ouvert le socket en écoute.



Si le run de chaque thread d'écoute du serveur est sous try: except:
alors chaque thread retournera toujours proprement, même si le/les
clients se plantent ... et alors le join aboutira correctement dans tous
les cas de figures.

Tu es d'accord ?


Je dois dire que j'ai pas suivi votre histoire de thread. Et en y
regardant de plus pret, je pense que le problème n'est absolument pas lié
aux threads. En fait, il n'existe pas de façon barbare de fermer un
socket. Le problème des TIME_WAIT viens soit d'une coupure brusque de la
connection réseau (machine distante qui plante ou connection entre les
deux machines subitement impossible), soit du fait qu'après un close, rien
ne garantit que tu puisses immédiatement faire un bind sur le même port.

En effet, close termine immédiatement puis c'est à l'OS de s'occuper de
finir de fermer la socket ce qui prend du temps. Essayer de l'ouvrir
immédiatement après un close n'est donc absolument pas garantit de
fonctionner.



Tout ce que je peux dire c'est que j'ai eu le problème de Chris il y a des
années, et que je l'ai résolu en utilisant la méthode que j'ai
préconisé ... mais pas inventé ... puisqu'on me l'a préconisé auparavant.

join apporte l'assurance que tous les threads sont sortis correctement ...
et donc dans le cas présent qu'ils ont géré la fermeture de leurs sockets
respectifs d'une façon que le développeur maîtrise.

Quelque part, ça me fait peut-être mieux comprendre pourquoi il n'y a pas
de "kill-thread" en Python ... mais ce n'est surement pas l'unique raison.


hg





Avatar
Christophe Cavalaria
hg wrote:

Tout ce que je peux dire c'est que j'ai eu le problème de Chris il y a des
années, et que je l'ai résolu en utilisant la méthode que j'ai
préconisé ... mais pas inventé ... puisqu'on me l'a préconisé auparavant.

join apporte l'assurance que tous les threads sont sortis correctement ...
et donc dans le cas présent qu'ils ont géré la fermeture de leurs sockets
respectifs d'une façon que le développeur maîtrise.


De toute façon, il me semblait que les sockets clients étaient fermés
directement par le thread principal avant que le programme quitte. Je ne
vois pas ce qui peut mal se passer dans ce cas, même si un thread fou ne
répond plus. Une fois l'application quittée, tout sera nettoyé par l'OS de
toute façon.

Quelque part, ça me fait peut-être mieux comprendre pourquoi il n'y a pas
de "kill-thread" en Python ... mais ce n'est surement pas l'unique raison.


Ce n'est pas une limitation du Python en tout cas. Par exemple, la lib SDL
qui fournit un accès multi-platforme aux threads pour du code C ne fournit
pas non plus cette opération pour les mêmes raisons.

1 2 3