How to close a blocking socket while it is waiting for data to be received?

I have a service that uses a blocking socket to receive data. The problem is that I don’t know how to close the socket correctly if it is still waiting for data. The following is a brief excerpt from how I open and wait for data: I do not want to use timeouts, because according to the python documentation, the socket must be blocked in order to use makefile .

Maybe I'm wrong, as I'm new to socket programming.

EDIT:

It should be noted that I cannot change the way the server works.

 import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((HOST, PORT)) reader = s.makefile("rb") line = reader.readline() 
+4
source share
4 answers

One solution to close this socket is to request the server close it.

If the server closes the client socket, the client will receive a "Connection reset by peer" message, and it may interfere with the reception of the lock.

Another solution would be to not use readline() and put a timeout on your socket (undefined wait can wait .... indefinitely)

+1
source

There is a fairly simple solution. Given that the socket and file are a reader file, for example rfile = socket.makefile('rb') , so that rfile.readline() returns immediately when the socket is closed, you need to do the following in a separate thread:

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

Calling socket.shutdown() will make rfile.readline() return an empty str or bytes , depending on the version of Python (2.x or 3.x respectively).

+3
source

I believe that if you just go in and close it from another thread, then the thread that tried to read it will return with an error. If you do not have multiple threads, you will have to refactor to use non-blocking mode ( os.O_NONBLOCK option when opening a socket).

+1
source

As you can see from a host of other somewhat confusing, often fragile or dangerous answers, this is a difficult question. Fortunately, you can get around all these problems by using non-blocking sockets instead. Consider this approach (use Twisted for simplicity):

 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() 
0
source

All Articles