J'ai un service qui utilise une socket de blocage pour recevoir des données. Le problème que j'ai est que je ne sais pas comment fermer correctement le socket s'il attend toujours des données. Vous trouverez ci-dessous un bref aperçu de la façon dont j'ouvre et j'attends des données: je ne veux pas implémenter des délais d'attente car, selon la documentation de python, le socket doit être bloquant pour utiliser makefile
.
Je vais peut-être me tromper complètement car je suis nouveau dans la programmation avec des sockets.
ÉDITER:
Il convient de noter que le I ne peut pas modifier le fonctionnement du serveur.
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
reader = s.makefile("rb")
line = reader.readline()
4 réponses
Une solution pour fermer ce socket consiste à demander au serveur de le fermer.
Si le serveur ferme le socket client, le client recevra une erreur de «réinitialisation de la connexion par l'homologue», ce qui peut interrompre la réception bloquante.
Une autre solution serait de ne pas utiliser readline()
et de mettre un timeout sur votre socket (une attente indéfinie pourrait attendre .... indéfiniment)
Comme vous pouvez le voir dans la variété d'autres réponses quelque peu confuses, souvent fragiles ou dangereuses, c'est une question délicate. Heureusement, vous pouvez contourner tous ces problèmes en utilisant des sockets non bloquants à la place. Considérez cette approche (en utilisant Twisted pour plus de simplicité):
from twisted.internet.protocol import ClientFactory
from twisted.protocols.basic import LineOnlyReceiver
from twisted.protocols.policies import TimeoutMixin
from twisted.internet import reactor
class YourClientProtocol(LineOnlyReceiver, TimeoutMixin):
def connectionMade(self):
# Initiate the timeout
self.setTimeout(30)
def lineReceived(self, line):
# Reset the countdown
self.resetTimeout()
# And process the line somehow
if line == "great justice":
print "for the win!"
def timeoutConnection(self):
# Report the timeout
print "Timed out waiting for a line"
# Drop the connection
self.transport.loseConnection()
def connectionLost(self, reason):
# Let the program complete
reactor.stop()
# Set up a connection
clientFactory = ClientFactory()
clientFactory.protocol = YourClientProtocol
reactor.connectTCP(HOST, PORT)
# Start the main loop, which can handle timed and
# network events simultaneously
reactor.run()
Je crois que si vous allez de l'avant et le fermez à partir d'un autre fil, le fil qui tentait de le lire reviendra avec une erreur. Si vous n'avez pas plusieurs threads, vous devrez refactoriser pour utiliser le mode non bloquant (option os.O_NONBLOCK
lorsque vous ouvrez le socket).
Il existe une solution assez simple. Étant donné un socket et un objet fichier lecteur comme rfile = socket.makefile('rb')
, afin de faire rfile.readline()
retourner immédiatement lorsque le socket est fermé, vous devez exécuter ce qui suit dans un thread séparé:
socket.shutdown(socket.SHUT_RDWR)
socket.close()
Appeler socket.shutdown()
sera faire rfile.readline()
retourner un str
ou bytes
vide, selon la version de Python (2.x ou 3.x respectivement).
Questions connexes
De nouvelles questions
python
Python est un langage de programmation multi-paradigme, typé dynamiquement et polyvalent. Il est conçu pour être rapide à apprendre, comprendre, utiliser et appliquer une syntaxe propre et uniforme. Veuillez noter que Python 2 est officiellement hors support à partir du 01-01-2020. Néanmoins, pour les questions Python spécifiques à la version, ajoutez la balise [python-2.7] ou [python-3.x]. Lorsque vous utilisez une variante Python (par exemple, Jython, PyPy) ou une bibliothèque (par exemple, Pandas et NumPy), veuillez l'inclure dans les balises.