Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does the TCPServer + BaseRequestHandler in Python's SocketServer close the socket after each call to handle()?

Tags:

python

sockets

I'm writing a client/server application in Python and I'm finding it necessary to get a new connection to the server for each request from the client. My server is just inheriting from TCPServer and I'm inheriting from BaseRequestHandler to do my processing. I'm not calling self.request.close() anywhere in the handler, but somehow the server seems to be hanging up on my client. What's up?

like image 826
Jeff Hammerbacher Avatar asked Jan 14 '10 19:01

Jeff Hammerbacher


People also ask

What is a SocketServer class?

The SocketServer module is a framework for creating network servers. It defines classes for handling synchronous network requests (the server request handler blocks until the request is completed) over TCP, UDP, Unix streams, and Unix datagrams.

What is Serve_forever Python?

serve_forever (poll_interval=0.5) Handle requests until an explicit shutdown() request. Poll for shutdown every poll_interval seconds. Ignores the timeout attribute.

What is socket server?

Sockets are commonly used for client and server interaction. Typical system configuration places the server on one machine, with the clients on other machines. The clients connect to the server, exchange information, and then disconnect. A socket has a typical flow of events.

How do I create a socket server in Python?

Python Socket Server To use python socket connection, we need to import socket module. Then, sequentially we need to perform some task to establish connection between server and client. We can obtain host address by using socket. gethostname() function.


3 Answers

Okay, I read the code (on my Mac, SocketServer.py is at /System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/).

Indeed, TCPServer is closing the connection. In BaseServer.handle_request, process_request is called, which calls close_request. In the TCPServer class, close_request calls self.request.close(), and self.request is just the socket used to handle the request.

So the answer to my question is "Yes".

like image 57
Jeff Hammerbacher Avatar answered Oct 05 '22 05:10

Jeff Hammerbacher


  1. tcpserver really close connection each time after 'handle'
  2. the follow code doesn't work while peer closing

    def handle(self):
        while 1:
        try:
            data = self.request.recv(1024)
            print self.client_address, "sent", data
        except:
            pass
    

    this may be better:

    def handle(self):
        while(1):
            try:
                self.data = self.request.recv(1024)
                if not self.data:
                    print "%s close" % self.client_address[0]
                    break
                print "%s wrote:" % self.client_address[0], self.data
            except:
                print "except"
                break
    
    1. reuseaddr doesn't work as it's too late after binding
    server.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
like image 44
woso Avatar answered Oct 05 '22 04:10

woso


According to the docs, neither TCPServer nor BaseRequestHandler close the socket unless prompted to do so. The default implementations of both handle() and finish() do nothing.

A couple of things might be happening:

  • You are closing the socket itself or the request which wraps it, or calling server_close somewhere.
  • The socket timeout could have been hit and you have implemented a timeout handler which closes the socket.
  • The client could be actually closing the socket. Code would really help figuring this out.

However, my testing confirms your results. Once you return from handle on the server, whether connecting through telnet or Python's socket module, your connection shows up as being closed by the remote host. Handling socket activity in a loop inside handle seems to work:

def handle(self):
    while 1:
        try:
            data = self.request.recv(1024)
            print self.client_address, "sent", data
        except:
            pass

A brief Google Code Search confirms that this is a typical way of handling a request: 1 2 3 4. Honestly, there are plenty of other networking libraries available for Python that I might look to if I were facing a disconnect between the abstraction SocketServer provides and my expectations.

Code sample that I used to test:

from SocketServer import BaseRequestHandler, TCPServer

class TestRequestHandler(BaseRequestHandler):
    def handle(self):
        data = self.request.recv(1024)
        print self.client_address, "sent", data
        self.request.send(data)

class TestServer(TCPServer):
    def __init__(self, server_address, handler_class=TestRequestHandler):
        TCPServer.__init__(self, server_address, handler_class)

if __name__ == "__main__":
    import socket

    address = ('localhost', 7734)
    server = TestServer(address)
    server.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
like image 23
Michael Greene Avatar answered Oct 05 '22 05:10

Michael Greene