Skip to content Skip to sidebar Skip to footer

Python : How To Close A Udp Socket While Is Waiting For Data In Recv?

let's consider this code in python: import socket import threading import sys import select class UDPServer: def __init__(self): self.s=None self.t=None d

Solution 1:

The usual solution is to have a pipe tell the worker thread when to die.

  1. 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 and os.write) or turn into Python file objects using os.fdopen.

  2. 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.

  3. 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?"