Python Forum
Thread Rating:
  • 2 Vote(s) - 5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Bare Minimum Sockets
#1
Getting started using sockets is not easy. It's complicated, unintuitive, and the documentation is less than perfect. I think it could be useful to have a "bare minimum" example of how to do certain things, perhaps with some building upon the others as I go. To that end, here's the easiest way to have a server that listens for a client to connect. All it does is print out whatever the client sends, and then it shuts down. Getting it to handle more than one client would be as easy as wrapping everything after sock.accept() in a while True loop.

To test it, I recommend curl.

import socket


def read_from_client(client):
    line_separator = b"\r\n"
    buffer = b""
    # a client let's us know it's done sending, by sending a blank line
    while buffer != line_separator:
        # read from the socket until we have a complete line
        while line_separator not in buffer:
            buffer += client.recv(4096)
        # split the first complete line off of the rest of the buffer
        (line, buffer) = buffer.split(line_separator, 1)
        # re-add the newline we just split on, so the line is unchanged
        line += line_separator
        yield line

# create a listening socket
with socket.socket(socket.AF_INET6) as sock:
    # set the ReuseAddress option, so we can restart the script
    #  regardless of errors, to ease testing
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    # ip and port to listen to (::1 is ip6's "localhost")
    sock.bind(("::1", 9753))
    # let the OS know we're ready to start handling clients,
    #  and they can queue up for us to handle
    sock.listen()

    # block until there's a client socket
    (client_sock, addr) = sock.accept()
    with client_sock:
        # iterate over each line the client sends us
        for line in read_from_client(client_sock):
            print(line)
Output:
# (either background it, or run curl in another terminal) > python server.py b'GET / HTTP/1.1\r\n' b'Host: localhost:9753\r\n' b'User-Agent: curl/7.56.0\r\n' b'Accept: */*\r\n'
Output:
>curl -v localhost:9753/ * Trying ::1... * TCP_NODELAY set * Connected to localhost (::1) port 9753 (#0) > GET / HTTP/1.1 > Host: localhost:9753 > User-Agent: curl/7.56.0 > Accept: */* > * Empty reply from server * Connection #0 to host localhost left intact curl: (52) Empty reply from server
So you can see that curl isn't thrilled about the server not sending any sort of reply back, but the server did get all the data, and echo it out. So... mission accomplished :)
Reply
#2
Obviously, this is not good enough for real-world use.  As a simple example of why... let's say a client uses a while True block to constantly stream an infinite number of characters to the server, without ever sending a newline.  The server process fail with a MemoryError.  But that's why the "bare minimum" is almost never used in the real world, regardless of topic.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020