2

I'm using python socket server to which I connect with Android and periodically send messages. I have a problem that the request is closed on every sent message and i need it to remain opened until Android decides to close it.

Curentlly it looks like this:

class SingleTCPHandler(SocketServer.StreamRequestHandler):
    def handle(self):
    try:
        while True:
            message = self.rfile.readline().strip()  # clip input at 1Kb            
            my_event = pygame.event.Event(USEREVENT, {'control':message})
            pygame.event.post(my_event)
    except KeyboardInterrupt:
        sys.exit(0)
    finally:
        self.request.close()

I've solved this by adding a while True in my handle() definition, however, this was criticized as a bad solution and that the right way to go is to override the process_request and shutdown methods.

Attempt of solution

I removed the while from the code, connected to the server locally with netcat, sent a message and went to see when will the connection be closed.

I wanted to see what is the method after which the connection is being closed to figuer out what i have to override.

I have stepped with the debugger through the serve_forever() and followed it to this part of code:

> /usr/lib/python2.7/threading.py(495)start()
    494         try:
--> 495             _start_new_thread(self.__bootstrap, ())
    496         except Exception:

After line 495 is passed (i can't step into it) the connection is closed.

I somehow doubt that it's such a hustle to maintain a connection via socket, that is basically the reason why we chosen to communicate over a socket, to have a continuous connection and not a 'one connection per sent message' system.

Ideas on implementation, or links?

1 Answer 1

9

The handle method is called for each client connection, and the connection is closed when it returns. Using a while loop is fine. Exit the loop when the client closes the connection.

Example (Python 3 syntax):

class EchoHandler(socketserver.StreamRequestHandler):

    def setup(self):
        print('{}:{} connected'.format(*self.client_address))

    def handle(self):
        while True:
            data = self.request.recv(1024)
            if not data: break
            self.request.sendall(data)

    def finish(self):
        print('{}:{} disconnected'.format(*self.client_address))
Sign up to request clarification or add additional context in comments.

5 Comments

The above doesn't seem to work in Linux with Python 2.6.6. self.request.recv(1024) does go in a loop until the end, but then does not exist when the client finished sending all data ... it just keeps waiting on the socket.
Did the client close the socket or at least call shutdown for send? Recv will block otherwise.
I figured it out. The problem is with bidir comm on the same connection; that's trickier than the above echo server where the server sends data after each received 1024 chunk; works fine with blocking sockets. For my bidir comm, the sever must first receive all data, then send to client. But both are blocking their sockets so the server doesn't know when client finished (client doesn't close the connection) and both wait... I had to hint the server when data ends but also used a timeout on the connection (not socket) so that recv doesn't block indefinitely when client doesn't follow protocol.
Right, you have to implement a protocol for sending and receiving message packets because TCPIP is a streaming protocol. Another answer of mine explains some alternatives.
Indeed, and thanks for the link. That was not the biggest issue for me; it was the case when the client didn't follow protocol, which was resulting in both server and client waiting indefinitely. I had to use a timeout but on the connection, not the socket, so that recv() can raise an exception.

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.