4

I've created a class for a server with the declaration:

class myServer(socketserver.BaseRequestHandler):  
    def handle(self):  
        pass

And started it with:

someServer = socketserver.UDPServer((HOST, PORT), myServer)  
someServer.serve_forever()

My question is: how can I get the server to shutdown itself? I've seen it has a base class (of a base class) called BaseServer with a shutdown method. It can be called on someServer with someServer.shutdown() but this is from the outside of the server itself.

shwartz
  • 631
  • 3
  • 13
  • 29

3 Answers3

1

You could use twisted. Its about the best networking lib for python, here is an example of a UDP server here is (taken from the twisted documentation) the simplest UDP server ever written;

#!/usr/bin/env python

# Copyright (c) 2001-2009 Twisted Matrix Laboratories.
# See LICENSE for details.

from twisted.internet.protocol import DatagramProtocol
from twisted.internet import reactor

# Here's a UDP version of the simplest possible protocol
class EchoUDP(DatagramProtocol):
    def datagramReceived(self, datagram, address):
        self.transport.write(datagram, address)

def main():
    reactor.listenUDP(8000, EchoUDP())
    reactor.run()

if __name__ == '__main__':
    main()

You can then close this down by calling self.transport.loseConnection() When you are ready or a specific event happens.

Jakob Bowyer
  • 33,878
  • 8
  • 76
  • 91
  • Hmmm... I should've stated I'm not allowed to use non-standard libraries. Thanks. – shwartz Mar 03 '11 at 09:24
  • Why are you not allowed to use anything BUT stdlib? socket is a nasty trap that many people fall into. – Jakob Bowyer Mar 03 '11 at 09:54
  • Because it's for an assignment in a computer networking course on DNS and even though socket programming isn't the main point of the assignment, they still chose to disallow the use of anything besides the standard library. Specifically, dnslib but other external libraries as well. Anyway, the deadline's passed. I hope what I did was sufficient. – shwartz Mar 11 '11 at 10:52
  • There were lots of problems with this assignment for the entire course so eventually I re-submitted this and this time I implemented your idea. It worked. I tweaked it a bit and used a lock with `acquire` and `release` so the server can release the lock when it is done and then the thread responsible for shutting it down acquires the lock and shuts the server down. – shwartz May 25 '11 at 21:31
  • I think I meant to write that for a different answer. – shwartz Dec 01 '13 at 17:09
1

By using threads. Serving by one thread and going via another after your timeout. Consider this working example. Modify it for your UDPServer

import threading
import time
import SimpleHTTPServer
import SocketServer

PORT = 8000
Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", PORT), Handler)

def worker():

    # minimal web server.  serves files relative to the
    print "serving at port", PORT
    httpd.serve_forever()

def my_service():
    time.sleep(3)
    print "I am going down"
    httpd.shutdown()

h = threading.Thread(name='httpd', target=worker)
t = threading.Thread(name='timer', target=my_service)

h.start()
t.start()
Senthil Kumaran
  • 54,681
  • 14
  • 94
  • 131
0

The server instance is available as self.server in the handler class. So you can call self.server.shutdown() in the handle method.

Petri Lehtinen
  • 1,995
  • 2
  • 17
  • 22
  • Sounds good. Too bad my deadline's passed but I still tried that out, with a `print("before")`, `self.server.shutdown()` and a `print("after")` but for some reason it didn't pass the `shutdown` command. – shwartz Mar 11 '11 at 11:03
  • This didn't work for me either. The program deadlocks on windows (can't Control+C out, have to Control+Break out). Seems like server.shutdown() cannot be called from within the RequestHandler. My guess is that shutdown waits for all requests to be done. That bit of code in request handler waits for the server to be shut down. Instant deadlock. Using threads to delay a bit, then call "server.shutdown()" works. Messy, but maybe necessary? – rocketmonkeys Sep 17 '11 at 21:13
  • 3
    Docstring of `shutdown()` method says _Stops the serve_forever loop. Blocks until the loop has finished. This must be called while serve_forever() is running in another thread, or it will deadlock._ See [source](http://hg.python.org/cpython/file/2.7/Lib/SocketServer.py#l243) in SocketServer.py file. – Piotr Dobrogost Aug 13 '12 at 22:35