3

I'm implementing a simple server which should print a message if nothing is received for 3 seconds.

Handler

class SingleTCPHandler(SocketServer.StreamRequestHandler):
 def handle(self):
 while True:
 message = self.rfile.readline().strip()
 print message

Server

class SimpleServer(SocketServer.TCPServer):
 timeout = 3
 def handle_timeout(self):
 print "Timeout"
 def __init__(self, server_address, RequestHandlerClass):
 SocketServer.TCPServer.__init__(self, server_address, RequestHandlerClass)

Here I'm extending the TCPServer for testing the timeout method. I've set the timeout atribute to 3. According to the docs, if that time passes and no messages are sent to the client handle_timeout() is called which, in my case, just prints 'Timeout'.

BaseServer.timeout

Timeout duration, measured in seconds, or None if no timeout is desired. If handle_request() receives no incoming requests within the timeout period, the handle_timeout() method is called.

I start the server, and observe it's output. When i connect to it and send some messages, they are normally printed. However, if I don't send anything for 3 seconds or more, nothing happens. As if the timeout and handle_timeout() haven't been implemented.

What could be the source of this behavior?

asked Mar 29, 2013 at 15:09

5 Answers 5

5

you must not call server_forever() method for app loop. try this one instead:

while True:
 self.handle_request()

handle_timeout() works for me then.

answered Oct 14, 2013 at 23:38
Sign up to request clarification or add additional context in comments.

Comments

3

Can you try declare the timeout at self.timeout (i.e make it a instance field instead of class variable ?)

EDIT (here is the code)

def handle_request(self):
 """Handle one request, possibly blocking.
 Respects self.timeout.
 """
 # Support people who used socket.settimeout() to escape
 # handle_request before self.timeout was available.
 timeout = self.socket.gettimeout()
 if timeout is None:
 timeout = self.timeout
 elif self.timeout is not None:
 timeout = min(timeout, self.timeout)
 fd_sets = select.select([self], [], [], timeout)
 if not fd_sets[0]:
 self.handle_timeout()
 return
 self._handle_request_noblock()
answered Mar 29, 2013 at 15:18

2 Comments

Will try to implement this if a prettier solution doesn't show up. It seems like an unnecessary hack with the existence of the handle_timeout()?
From the code it seems the "static"/class timeout variable isn't taken into account :( so maybe changing the socket timeout or make it to return None will help (since then, self.timeout could take its role)
3

Here is the document of serve_forever():

Handle requests until an explicit shutdown() request. Poll for shutdown every poll_interval seconds. Ignores self.timeout. If you need to do periodic tasks, do them in another thread

So the serve_forever() will only check if shutdown() is called every poll_interval whose default value is 0.5 seconds. And only handle_request() care about the timeout.

Here is the code for serve_forever() and handle_request().

answered Jan 7, 2015 at 23:43

Comments

1

In the end, I dropped the socketserver module and went directly with socket module, in which timeout worked.

TIMEOUT = 3
HOST = '192.0.0.202' 
PORT = 2000 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
while 1:
 conn, addr = s.accept()
 conn.settimeout(TIMEOUT)
 while 1:
 try:
 data = conn.recv(1024)
 #Do things
 except socket.timeout:
 #Timeout occurred, do things
 if not data or P=='end':
 print 'Connection lost. Listening for a new controller.' 
 break
conn.close()
answered May 8, 2013 at 7:48

Comments

1

First of all, what do you mean by "[the server] should print a message if nothing is received for 3 seconds."?

Do you mean that the server should ...

  1. shutdown if it hadn't any new requests in certain period?
  2. close a connection if it isn't finished in a certain period?

In the first case you can use BaseServer.timeout but you would also have to use BaseServer.handle_request() instead of BaseServer.server_forever().

In the second case you should have set the timeout for the SingleTCPHandler:

class SingleTCPHandler(SocketServer.StreamRequestHandler):
 timeout = 3
 def handle(self):
 while True:
 message = self.rfile.readline().strip()
 print message

For people who want to use their own implementation of BaseRequestHandler:

class MyRequestHandler(SocketServer.BaseRequestHandler):
 def handle(self):
 self.request.settimeout(3)
answered Feb 2, 2015 at 17:44

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.