I want to write a simple client/server application in Python to send and receive JSON objects. The server is running fine and receives input from the client-side:
λ python server.py
Server running on localhost:9091
Handle request from ('127.0.0.1', 50877)
Received command: {'command': 'hello'}
Sent reply: {'ok': True}
On the client-side im getting the following output:
λ python client.py
Socket created
Socket connected to ('localhost', 9091)
Sent message {'command': 'hello'} to ('localhost', 9091)
Traceback (most recent call last):
File "C:\Users\Admin\Sample\client.py", line 25, in
<module>
connection.send_request(req)
File "C:\Users\Admin\Sample\client.py", line 19, in
send_request
reply = json.load(fp=socket_input)
File "C:\Users\Admin\AppData\Local\Programs\Python\Python39\lib\json\__init__.py", line 293, in load
return loads(fp.read(),
File "C:\Users\Admin\AppData\Local\Programs\Python\Python39\lib\socket.py", line 704, in readinto
return self._sock.recv_into(b)
ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host
Client
import json
import socket
class ServerConnection:
def __init__(self, host: str, port: int):
self._host = host
self._port = port
def send_request(self, request: any) -> str:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((self._host, self._port))
print(f"Connected to {(self._host, self._port)}")
sock.sendall(bytes(json.dumps(request), "utf-8"))
sock.shutdown(socket.SHUT_WR)
print(f"Sent message {request} to {(self._host, self._port)}")
with sock.makefile(mode="r", encoding="utf-8") as socket_input:
reply = json.load(fp=socket_input)
print(f"Received: {reply}")
req = {"command": "hello"}
connection = ServerConnection("localhost", 9091)
connection.send_request(req)
Server
import io
import json
import socketserver
host: str = "localhost"
port: int = 9091
class RequestHandler(socketserver.StreamRequestHandler):
def send_reply(self, reply: any):
json.dump(
obj=reply,
fp=io.TextIOWrapper(self.wfile, encoding="utf-8"),
sort_keys=True,
)
print(f"Sent reply: {reply}")
def handle(self) -> None:
print(f"Handle request from {self.client_address}")
command = json.load(
fp=io.TextIOWrapper(self.rfile, encoding="utf-8"),
)
print(f"Received command: {command}")
reply = {"ok": True}
self.send_reply(reply)
class Server(socketserver.TCPServer):
def __init__(self, server_address):
super().__init__(
server_address=server_address,
RequestHandlerClass=RequestHandler,
bind_and_activate=True,
)
self._active = True
def shutdown(self) -> None:
self._active = False
def continue_handling(self) -> bool:
return self._active
with Server(
server_address=(host, port),
) as server:
print(f"Server running on {host}:{port}")
while server.continue_handling():
server.handle_request()
print(f"Server shut down on {host}:{port}")
I would like to understand why this happens. After researching for a bit I found these possible reasons:
- Running out of system resources (unlikely)
- Too many requests to the server (it's just a single request here, unlikely)
- Firewall problems (I tried turning my firewall off temporarily)
I would be very grateful if someone spots a possible error in my code or points out what parts of my system configuration might be responsible for this behavior.