def handle(self):
# self.request is the TCP socket connected to the client
- self.data = self.request.recv(1024).strip()
- print("Received from {}:".format(self.client_address[0]))
- print(self.data)
+ pieces = [b'']
+ total = 0
+ while b'\n' not in pieces[-1] and total < 10_000:
+ pieces.append(self.request.recv(2000))
+ total += len(pieces[-1])
+ self.data = b''.join(pieces)
+ print(f"Received from {self.client_address[0]}:")
+ print(self.data.decode("utf-8"))
# just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
+ # after we return, the socket will be closed.
if __name__ == "__main__":
HOST, PORT = "localhost", 9999
class MyTCPHandler(socketserver.StreamRequestHandler):
def handle(self):
- # self.rfile is a file-like object created by the handler;
- # we can now use e.g. readline() instead of raw recv() calls
- self.data = self.rfile.readline().strip()
- print("{} wrote:".format(self.client_address[0]))
- print(self.data)
+ # self.rfile is a file-like object created by the handler.
+ # We can now use e.g. readline() instead of raw recv() calls.
+ # We limit ourselves to 10000 bytes to avoid abuse by the sender.
+ self.data = self.rfile.readline(10000).rstrip()
+ print(f"{self.client_address[0]} wrote:")
+ print(self.data.decode("utf-8"))
# Likewise, self.wfile is a file-like object used to write back
# to the client
self.wfile.write(self.data.upper())
The difference is that the ``readline()`` call in the second handler will call
``recv()`` multiple times until it encounters a newline character, while the
-single ``recv()`` call in the first handler will just return what has been
-received so far from the client's ``sendall()`` call (typically all of it, but
-this is not guaranteed by the TCP protocol).
+the first handler had to use a ``recv()`` loop to accumulate data until a
+newline itself. If it had just used a single ``recv()`` without the loop it
+would just have returned what has been received so far from the client.
+TCP is stream based: data arrives in the order it was sent, but there no
+correlation between client ``send()`` or ``sendall()`` calls and the number
+of ``recv()`` calls on the server required to receive it.
This is the client side::
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
# Connect to server and send data
sock.connect((HOST, PORT))
- sock.sendall(bytes(data + "\n", "utf-8"))
+ sock.sendall(bytes(data, "utf-8"))
+ sock.sendall(b"\n")
# Receive data from the server and shut down
received = str(sock.recv(1024), "utf-8")
- print("Sent: {}".format(data))
- print("Received: {}".format(received))
+ print("Sent: ", data)
+ print("Received:", received)
The output of the example should look something like this:
def handle(self):
data = self.request[0].strip()
socket = self.request[1]
- print("{} wrote:".format(self.client_address[0]))
+ print(f"{self.client_address[0]} wrote:")
print(data)
socket.sendto(data.upper(), self.client_address)
sock.sendto(bytes(data + "\n", "utf-8"), (HOST, PORT))
received = str(sock.recv(1024), "utf-8")
- print("Sent: {}".format(data))
- print("Received: {}".format(received))
+ print("Sent: ", data)
+ print("Received:", received)
The output of the example should look exactly like for the TCP server example.