keepcalculator

06 Numbers and Powers

Python TCP Sockets: Send & Receive Data

Card No. 06·65131 · Updated · Standard formula, shown below

This guide shows you how to create a simple TCP client-server pair in Python to send and receive text data. You’ll write two scripts: a server that listens for connections and echoes back what it receives, and a client that connects, sends a message, and prints the response. No external libraries are needed—just Python’s built-in socket module.

What You’ll Need

  • Python 3.6 or newer installed on your machine.
  • Basic familiarity with running Python scripts from the terminal.
  • Two terminal windows (or two machines on the same network) to test the client and server.

Step-by-Step

  1. Create the server script. Open a text editor and create a file named server.py. This script will bind to a port, listen for incoming connections, and handle each client in a loop.
  2. Write the server code. Copy the following into server.py:

    import socket
    
    HOST = '127.0.0.1'  # localhost
    PORT = 65432        # non-privileged port
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        print('Server listening on', HOST, PORT)
        conn, addr = s.accept()
        with conn:
            print('Connected by', addr)
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                print('Received:', data.decode())
                conn.sendall(data)  # echo back
        
  3. Create the client script. Create another file named client.py in the same directory.
  4. Write the client code. Copy the following into client.py:

    import socket
    
    HOST = '127.0.0.1'
    PORT = 65432
    
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((HOST, PORT))
        s.sendall(b'Hello, server!')
        data = s.recv(1024)
    
    print('Received', repr(data))
        
  5. Run the server. In the first terminal, run python server.py. You should see “Server listening on 127.0.0.1 65432”. The script will block waiting for a connection.
  6. Run the client. In the second terminal, run python client.py. The client will connect, send the message, and print the echoed response. The server terminal will show the received message and then exit after the client closes the connection.
  7. Extend to multiple messages. The current server handles only one connection. To accept multiple clients, wrap the accept-and-handle part in an outer loop. For example:

    while True:
        conn, addr = s.accept()
        with conn:
            print('Connected by', addr)
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
        
  8. Send multiple messages from the client. To send more than one message, keep the connection open and use a loop. For example:

    with socket.socket(...) as s:
        s.connect((HOST, PORT))
        for msg in [b'First', b'Second']:
            s.sendall(msg)
            print(s.recv(1024))
        
  9. Handle larger data. The recv(1024) call receives at most 1024 bytes at once. For larger messages, you need to loop until all data is received. A simple approach is to send the message length first, then the data, and read until you have that many bytes. Or, for text, send a newline terminator and read until you see it.

Common Mistakes

  • Using send() instead of sendall(). send() may send only part of the data; sendall() keeps sending until all data is sent. Always use sendall() for reliability.
  • Forgetting to decode bytes. Data over sockets is bytes. Use .decode() when printing or processing text, and .encode() when sending strings.
  • Binding to a port already in use. If you get “Address already in use”, the previous server didn’t close properly. Wait a few seconds or use SO_REUSEADDR (see Tips).
  • Assuming recv() gets the whole message. TCP is a stream, not a message boundary. A single recv() may return partial data or multiple messages combined. You need to define your own framing (e.g., message length prefix).

Tips

  • Set a timeout on the socket to avoid hanging forever: s.settimeout(5) will raise a socket.timeout exception if no data arrives within 5 seconds.
  • Use with statements for sockets to ensure they are closed properly.
  • To allow the server to restart quickly, set SO_REUSEADDR before binding:
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        
  • For production, use threading or asyncio to handle multiple clients concurrently. The simple loop above blocks on accept() and then on recv(), so it can’t handle a second client while handling the first.
  • When sending text, always encode to UTF-8 explicitly: msg.encode('utf-8').

Troubleshooting

  • Connection refused. The server isn’t running, or the port is wrong. Check that the server is listening (you should see the “Server listening” message) and that both scripts use the same port.
  • No output from server. The server may be stuck on accept() waiting for a connection. Ensure the client is running and the IP/port match.
  • Address already in use. The previous server process is still holding the port. Wait a few seconds or kill the process. On Linux/macOS, you can use lsof -i :65432 to find the PID.
  • Client sends but server doesn’t receive. Check for firewalls. On Windows, you may need to allow Python through the firewall. On Linux, ensure the port isn’t blocked.
  • Data appears garbled. Likely an encoding mismatch. Ensure both sides use the same encoding (UTF-8 is standard).
  • Client hangs on recv(). The server may have closed the connection without sending data. In that case, recv() returns an empty bytes object, which you should check for and break out of the loop.

Frequently Asked Questions

  1. What is the difference between TCP and UDP? TCP is connection-oriented and guarantees delivery and order; UDP is connectionless and does not guarantee delivery or order. For most data where reliability matters, use TCP.
  2. How do I send JSON data? Convert the dictionary to a JSON string with json.dumps(), encode it, and send it. On the receiving side, decode and then use json.loads().
  3. Can I use sockets across different machines? Yes. Replace HOST with the server’s IP address (e.g., 192.168.1.10) and ensure the port is open in the server’s firewall.
  4. How do I handle multiple clients at once? Use the threading module: spawn a new thread for each accepted connection, or use asyncio for asynchronous I/O.
  5. Why does recv() return less data than I sent? TCP is a stream; recv() returns whatever is currently available, up to the buffer size. You must loop until you have all the data, based on a length prefix or a delimiter.
  6. What is the maximum message size I can send? There is no hard limit, but practically you should break large data into chunks. The socket buffer size is typically 64KB, but you can send more by looping with sendall().

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →