mirror of
https://github.com/python/cpython.git
synced 2025-12-31 12:33:28 +00:00
gh-112020: Rework socketserver examples to be correct (#129741)
gh-112020: Rework socketserver examples to be correct. Outdated code updated, the BaseRequestHandler example is now much more illustrative instead of the bad idea of a single recv() call for TCP. tested, they now work.
This commit is contained in:
parent
51b4edb1a4
commit
78377c788e
1 changed files with 28 additions and 17 deletions
|
|
@ -499,11 +499,17 @@ This is the server side::
|
|||
|
||||
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
|
||||
|
|
@ -520,20 +526,24 @@ objects that simplify communication by providing the standard file interface)::
|
|||
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::
|
||||
|
|
@ -548,13 +558,14 @@ 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:
|
||||
|
|
@ -599,7 +610,7 @@ This is the server side::
|
|||
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)
|
||||
|
||||
|
|
@ -624,8 +635,8 @@ This is the client side::
|
|||
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.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue