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?

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.

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()

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().

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()

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)

Comments

Your Answer

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.