Echo Server and Client

Server

./code/echo-hello/server.py
 1#!/usr/bin/env python3
 2import socket
 3import threading
 4
 5# nc localhost 6006
 6
 7
 8def run_server():
 9    sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
10    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
11    sock.bind(("", 6006))
12    #  sock.setblocking(False) # It returns socket.BlockingIOError
13    sock.listen(2)  # backlog is 2
14    while True:
15        client_sock, addr = sock.accept()
16        assert isinstance(client_sock, socket.socket)
17        assert isinstance(addr, tuple)
18        assert isinstance(addr[0], str)
19        assert isinstance(addr[1], int)
20        print("Connected from", addr)  # Connected from ('127.0.0.1', 54266)
21        threading.Thread(target=handle_client, args=(client_sock,)).start()
22
23
24def handle_client(sock: socket.socket):
25    while True:
26        data = sock.recv(1024)
27        if not data:
28            break
29        sock.sendall(data.decode("utf-8").upper().encode())
30    print("Disconnected from", sock.getpeername())
31    sock.close()
32
33
34if __name__ == "__main__":
35    run_server()

To test the server, use nc localhost 6006 or use the following client.

Client

./code/echo-hello/client.py
1def main():
2    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
3    sock.connect(("localhost", 6006))
4    for i in range(5):
5        sock.send("hello".encode())
6        b = sock.recv(1024)
7        print(b.decode())
8        time.sleep(0.5)

Server2

With concurrent.futures.ThreadPoolExecutor.

./code/echo-hello/server2.py
 1#!/usr/bin/env python3
 2import socket
 3import threading
 4from concurrent.futures import ThreadPoolExecutor
 5
 6# nc localhost 6006
 7pool = ThreadPoolExecutor(max_workers=3)
 8
 9
10def run_server():
11    sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
12    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
13    sock.bind(("", 6006))
14    #  sock.setblocking(False) # It returns socket.BlockingIOError
15    sock.listen(2)  # backlog is 2
16    while True:
17        client_sock, addr = sock.accept()
18        assert isinstance(client_sock, socket.socket)
19        assert isinstance(addr, tuple)
20        assert isinstance(addr[0], str)
21        assert isinstance(addr[1], int)
22        print("Connected from", addr)  # Connected from ('127.0.0.1', 54266)
23        pool.submit(handle_client, client_sock)
24
25
26def handle_client(sock: socket.socket):
27    while True:
28        data = sock.recv(1024)
29        if not data:
30            break
31        sock.sendall(data.decode("utf-8").upper().encode())
32    print("Disconnected from", sock.getpeername())
33    sock.close()
34
35
36if __name__ == "__main__":
37    run_server()