closing a "forever" Server Socket

A

alessandro

Hi all,

This is my framework for create TCP server listening forever on a port
and supporting threads:


import SocketServer

port = 2222
ip = "192.168.0.4"
server_address = (ip, port)

class ThreadingTCPServer(SocketServer.ThreadingMixIn,
SocketServer.TCPServer): pass

class Handler(SocketServer.BaseRequestHandler):
def handle(self):
# my handler

print "Listening for events at " + ip + ":" + str(port)
monitor_server = ThreadingTCPServer(server_address, Handler)

try:
monitor_server.serve_forever()
except KeyboardInterrupt:
monitor_server.socket.close()
print "Bye."


This server will not run as a daemon and for quitting you have to send
the SIGINT signal with Ctrl-C. It will rise the KeyboardInterrupt
exception, during its handling I simply close the socket and print a
message.

I want to ask if someone knows a better way for closing a "forever
server" or if there is a lack in my design.

Thank you!

Alessandro
 
M

Matimus

I want to ask if someone knows a better way for closing a "forever
server" or if there is a lack in my design.

Generally you don't create a 'forever server'. You create an 'until I
say stop' server. I would do this by looking at the 'serve_forever'
method, and implementing my own 'serve_until_?' method that is similar,
but will stop if a flag is set. Then you have to create a method for
setting that flag. It could be as simple as a keypress, or you could
add a quit method to your dispatcher that sets the flag when a certain
address is visited. That second method probably needs some added
security, otherwise anybody can just visit 'your.server.com/quit' and
shut it down.
 
A

alessandro

thanks

infact the server_forever() method is only a serve() method inside an
infinite loop.

many thanks again,

Alessandro

Matimus ha scritto:
 
L

Laszlo Nagy

alessandro írta:
thanks

infact the server_forever() method is only a serve() method inside an
infinite loop.

many thanks again,
Here is a snipped that show a "software terminateable threading TCP
socker server". The "server" object is a SocketServer instance,
server_stopped is a threading.Event instance. You should also import the
"select" module.

srvfd = server.fileno()
while not server_stopped.isSet():
ready = select.select([srvfd], [], [], 1) # Give one second
for incoming connection so we can stop the server in seconds
if srvfd in ready[0]:
server.handle_request()
else:
pass # log('No incoming connection, retrying')
 
A

alessandro

Oh my God! it's really so complicated?

3 modules (threading, SocketServer, select) only for design a way to
shutdown a TCP server????
....but they told me that python was easy... :)

I'm working on a simulator and I have a monitor server that collects
information. I can shutdown it using Ctrl-C from the keyboard but for
my purpose could be very nice if I introduce a timer. So I could launch
my monitor like this:

../monitor 100

and my monitor will run for 100 seconds. For this I'm using the Timer
class provided by threading module, I have implemented a function like
this:

def shutdown():
sys.exit()

but it doesen't work because the server remain alive...maybe
SocketServer create immortal server...
I need only to close my application, there is a way to force the server
thread to close?

thanks!
Alessandro



Laszlo Nagy ha scritto:
alessandro írta:
thanks

infact the server_forever() method is only a serve() method inside an
infinite loop.

many thanks again,
Here is a snipped that show a "software terminateable threading TCP
socker server". The "server" object is a SocketServer instance,
server_stopped is a threading.Event instance. You should also import the
"select" module.

srvfd = server.fileno()
while not server_stopped.isSet():
ready = select.select([srvfd], [], [], 1) # Give one second
for incoming connection so we can stop the server in seconds
if srvfd in ready[0]:
server.handle_request()
else:
pass # log('No incoming connection, retrying')
 
L

Laszlo Nagy

alessandro írta:
Oh my God! it's really so complicated?

3 modules (threading, SocketServer, select) only for design a way to
shutdown a TCP server????
...but they told me that python was easy... :)
I believe that SockerServer was created for testing purposes, although
there are some programs using it in production. Yes, Python is easy. The
language is very clear, and you do not need to install third party
modules in order to create a server. :) Of course the easiest way is to
call serve_forever. Isn't it easy? The other way is to implement your
own message handling loop. The SocketServer is flexible enough to do
this; and I don't think it is complicated. 7 lines of code will allow
you to stop the server safely from anywhere, even from other threads.
Try to implement the same in C or Delphi...
but it doesen't work because the server remain alive...maybe
SocketServer create immortal server...
I need only to close my application, there is a way to force the server
thread to close?
In pure Python, no. Python threads are "cooperative". In other words,
they cannot be terminated from outside. A thread will stop after the
execution exits its "run" method. (You can, of course terminate the
tread with an operating system function, but it is not recommended.)


Here is a class that can be stopped with an event:

import threading

stop_requested = threading.Event()

class SoftWaitThread(threading.Thread):
"""SoftWaitThread can wait for a given time except if the thread was
asked
to terminate itself."""
def waitsome(self,amount=10):
"""Wait the specified amount of time.

This can be terminated by stop_requested within 0.1 seconds."""
for idx in range(int(10*amount)):
time.sleep(0.1)
if stop_requested.isSet():
break


Then you can do this:

class MyServerThread(SoftWaitThread):
def run(self):
server = MySocketServerClass()
srvfd = server.fileno()
while not stop_requested.isSet():
ready = select.select([srvfd], [], [], 1)
if srvfd in ready[0]:

server.handle_request()
else:
pass


And then:

import time
def main():
sth = MyServerThread() # Create your thread
sth.start() # Start handling requests in another thread
try:
time.sleep(TIMEOUT_IN_SECONDS) # Wait...
finally:
stop_requested.set() # Request the server thread to stop itself
sth.join() # Wait until the server thread stops
print "Stopped."

You could start several threads and request them to stop with the same
event. I hope this helps.

Laszlo


p.s.: Not all of the above was tested, be careful.
 
G

Gabriel Genellina

Oh my God! it's really so complicated?

3 modules (threading, SocketServer, select) only for design a way to
shutdown a TCP server????
...but they told me that python was easy... :)

You already have the answer: replace serve_forever with your own loop.
I'm working on a simulator and I have a monitor server that collects
information. I can shutdown it using Ctrl-C from the keyboard but for
my purpose could be very nice if I introduce a timer. So I could launch
my monitor like this:
./monitor 100

and my monitor will run for 100 seconds. For this I'm using the Timer

This is simple enough, I presume:

try:
stopt = time.time()+100
while time.time()<stopt:
server.handle_request()
except KeyboardInterrupt: pass
# shutdown

The drawback is that it won't leave the loop until a request arrives,
but this may not be a problem for you. (Other suggestions are more
complicated because of this issue.)


--
Gabriel Genellina
Softlab SRL






__________________________________________________
Preguntá. Respondé. Descubrí.
Todo lo que querías saber, y lo que ni imaginabas,
está en Yahoo! Respuestas (Beta).
¡Probalo ya!
http://www.yahoo.com.ar/respuestas
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,982
Messages
2,570,186
Members
46,739
Latest member
Clint8040

Latest Threads

Top