pythontcpserversocketserver

Allowing multiple requests under the same socket connection with python socketserver


I started a TCP server in Python and tried to send to it multiple requests using a single socket connection:

>>> import socket
>>> s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> s.connect(('127.0.0.1', 4444))
>>> message = b'hi'
>>> s.sendall(message)
>>> resp = s.recv(4096)
>>> resp
b'hello'
>>> # Now trying to send another message without restarting the socket
>>> s.sendall(message)
>>> resp = s.recv(4096)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine

The server rejects my second request, I'll have to close and restart the socket so I can send a new request.

This is how my server looks like:

import socketserver
class MyTCPServer(socketserver.BaseRequestHandler):
    def handle(self):
        message = self.request.recv(4096)
        self.request.sendall(b'hello')

server = socketserver.TCPServer(('127.0.0.1', 4444), MyTCPServer)
server.serve_forever()

How can I make the server keep the connection alive and thus accept multiple requests using a single socket?


Solution

  • Here's a sample that shows how the same connected socket can be used for multiple send/receive sequences.

    This is not meant to represent robust production-appropriate code:

    from socket import socket, AF_INET, SOCK_STREAM
    from socketserver import BaseRequestHandler, TCPServer
    from threading import Thread
    
    HOST = "localhost"
    PORT = 10101
    ADDR = HOST, PORT
    RECVBUF = 4096
    
    class MyHandler(BaseRequestHandler):
        def handle(self):
            while self.request.recv(RECVBUF):
                self.request.sendall(b"Hello world!")
    
    def server(tcpserver):
        tcpserver.serve_forever()
    
    def echo():
        with socket(AF_INET, SOCK_STREAM) as s:
            s.connect(ADDR)
            for _ in range(5): # do this multiple times with the same connected socket
                s.sendall(b"Some dummy data")
                print(s.recv(RECVBUF).decode())
    
    if __name__ == "__main__":
        with TCPServer(ADDR, MyHandler) as tcpserver:
            (t := Thread(target=server, args=[tcpserver])).start()
            echo()
            tcpserver.shutdown()
            t.join()
    

    Output:

    Hello world!
    Hello world!
    Hello world!
    Hello world!
    Hello world!