Python : How To Close A Udp Socket While Is Waiting For Data In Recv?
Solution 1:
The usual solution is to have a pipe tell the worker thread when to die.
Create a pipe using
os.pipe
. This gives you a socket with both the reading and writing ends in the same program. It returns raw file descriptors, which you can use as-is (os.read
andos.write
) or turn into Python file objects usingos.fdopen
.The worker thread waits on both the network socket and the read end of the pipe using
select.select
. When the pipe becomes readable, the worker thread cleans up and exits. Don't read the data, ignore it: its arrival is the message.When the master thread wants to kill the worker, it writes a byte (any value) to the write end of the pipe. The master thread then joins the worker thread, then closes the pipe (remember to close both ends).
P.S. Closing an in-use socket is a bad idea in a multi-threaded program. The Linux close(2) manpage says:
It is probably unwise to close file descriptors while they may be in use by system calls in other threads in the same process. Since a file descriptor may be re-used, there are some obscure race conditions that may cause unintended side effects.
So it's lucky your first approach did not work!
Solution 2:
This is not java. Good hints:
- Don't use threads. Use asynchronous IO.
- Use a higher level networking framework
Here's an example using twisted:
from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor, stdio
from twisted.protocols.basic import LineReceiver
classUDPLogger(DatagramProtocol):
defdatagramReceived(self, data, (host, port)):
print"received %r from %s:%d" % (data, host, port)
classConsoleCommands(LineReceiver):
delimiter = '\n'
prompt_string = 'myserver> 'defconnectionMade(self):
self.sendLine('My Server Admin Console!')
self.transport.write(self.prompt_string)
deflineReceived(self, line):
line = line.strip()
if line:
if line == 'quit':
reactor.stop()
elif line == 'start':
reactor.listenUDP(8888, UDPLogger())
self.sendLine('listening on udp 8888')
else:
self.sendLine('Unknown command: %r' % (line,))
self.transport.write(self.prompt_string)
stdio.StandardIO(ConsoleCommands())
reactor.run()
Example session:
My Server Admin Console!
myserver> foo
Unknown command: 'foo'
myserver> start
listening on udp 8888
myserver> quit
Post a Comment for "Python : How To Close A Udp Socket While Is Waiting For Data In Recv?"