I adapted the code below from the Python documentation here.
# filename: example.py
from datetime import datetime
import socket
import socketserver
import sys
import threading
import time
class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
data = str(self.request.recv(1024), 'ascii')
cur_thread = threading.current_thread()
response = bytes("{}: {}".format(cur_thread.name, data), 'ascii')
self.request.sendall(response)
class ThreadedTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
allow_reuse_address = True
def client(ip, port, message):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((ip, port))
sock.sendall(bytes(message, 'ascii'))
response = str(sock.recv(1024), 'ascii')
print("Received: {}".format(response))
if __name__ == "__main__":
HOST, PORT = "127.0.0.1", 9999
if sys.argv[1] == "server":
server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)
with server:
ip, port = server.server_address
print(f'{ip} {port}')
server_thread = threading.Thread(target=server.serve_forever)
server_thread.start()
# these work
client(ip, port, "Hello World 1 at " + str(datetime.now()))
time.sleep(1)
client(ip, port, "Hello World 2 at " + str(datetime.now()))
time.sleep(2)
client(ip, port, "Hello World 3 at " + str(datetime.now()))
if sys.argv[1] == "client":
# these do not work, why?
client(HOST, PORT, "Hello World 1 at " + str(datetime.now()))
time.sleep(1)
client(HOST, PORT, "Hello World 2 at " + str(datetime.now()))
time.sleep(2)
client(HOST, PORT, "Hello World 3 at " + str(datetime.now()))
Running this code as a server works as expected:
$ python3 example.py server
127.0.0.1 9999
Received: Thread-2: Hello World 1 at 2021-09-14 20:02:25.135218
Received: Thread-3: Hello World 2 at 2021-09-14 20:02:26.140889
Received: Thread-4: Hello World 3 at 2021-09-14 20:02:28.143664
I leave this terminal tab running (the program is waiting for additional clients to connect), open a new tab and run the following, but it produces an error:
$ python3 example.py client
Traceback (most recent call last):
File "/Users/ashroyer-admin/repo/phd-courses/2021-F-cloudcomp/thred.py", line 45, in <module>
client(HOST, PORT, "Hello World 1 at " + str(datetime.now()))
File "/Users/ashroyer-admin/repo/phd-courses/2021-F-cloudcomp/thred.py", line 20, in client
sock.connect((ip, port))
ConnectionRefusedError: [Errno 61] Connection refused
ConnectionRefused
typically means there is no server listening at the specified IP/Port (or its backlog is full, which is unlikely in this example). Chances are, the server
object is simply not running anymore by the time you try to connect the other terminal clients. Just because you left the server's terminal open doesn't mean the server itself is still running in that terminal.
The server is likely terminating after its main thread makes its 3 calls to client()
. You are running serve_forever()
in another thread, not in the main thread that creates the server
and calls client()
. There is nothing afterwards - no loop, no event, etc - that the code is waiting on to keep the script running so the server_thread
can continue servicing new clients.
When the with server:
block ends, the server
object gets closed. And when the main thread is done, the script exits.
What I would suggest is either:
get rid of server_thread
and the 3 calls to client()
altogether. Just call server.serve_forever()
after print(f'{ip} {port}')
, and then use other terminals to test your client()
code.
or, at least remove the with server:
block. Apparently, "the server thread isn't daemonic so it keeps running when main exits. Remove with server:
and it works fine." (thanks
@MarkTolonen)