Skip to main content

Example: A TCP Socket Echo Server in Python

Introduction

TCP (Transmission Control Protocol) is one of the most widely used protocols in the Internet. It provides reliable, ordered, and error-checked delivery of data between applications running on different devices. A TCP socket is an endpoint of a TCP connection, which is identified by an IP address and a port number. A TCP socket can send and receive data to and from another TCP socket over the network.


In this article, I will show you how to write a simple TCP socket echo server in Python, which is a program that listens for incoming connections from TCP socket clients, and echoes back whatever data it receives from them. This program can be useful for testing the functionality and performance of TCP sockets, as well as learning the basics of socket programming in Python.


Requirements

To write and run this program, you will need the following:

- A computer with Python 3 installed. You can download Python 3 from [here].

- A text editor or an IDE (Integrated Development Environment) of your choice. You can use any editor or IDE that supports Python, such as [Visual Studio Code], [PyCharm], [Sublime Text], etc.

- A network connection between your computer and another device that can run a TCP socket client. You can use another computer, a smartphone, a tablet, etc. Alternatively, you can run both the server and the client on the same computer, using the localhost address (127.0.0.1).


Code

The code for the TCP socket echo server is shown below. You can copy and paste it into your editor or IDE, or you can download it from [here]. The code has some comments that explain each step of the program.


  1. # Import socket module
  2. import socket
  3. # Define a function to handle each client connection
  4. def handle_client(client_socket, client_address):
  5.     # Print the client address
  6.     print(f"Connected to {client_address}")
  7.     # Loop until the client closes the connection or an error occurs
  8.     while True:
  9.         try:
  10.             # Receive data from the client, up to 1024 bytes
  11.             data = client_socket.recv(1024)
  12.             # If no data is received, break the loop
  13.             if not data:
  14.                 break
  15.             # Print the received data
  16.             print(f"Received from {client_address}{data}")
  17.             # Prepend "Server echo:" to the data and send it back to the client
  18.             response = b"Server echo:" + data
  19.             client_socket.send(response)
  20.             # Print the sent data
  21.             print(f"Sent to {client_address}{response}")
  22.         except Exception as e:
  23.             # Print the error message and break the loop
  24.             print(f"Error: {e}")
  25.             break
  26.     # Close the client socket
  27.     client_socket.close()
  28.     # Print the client address
  29.     print(f"Disconnected from {client_address}")
  30. # Create a TCP socket object
  31. server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  32. # Bind the socket to a local address and port
  33. server_socket.bind(("localhost"8080))
  34. # Listen for incoming connections, up to 5 in the queue
  35. server_socket.listen(5)
  36. # Print the server address and port
  37. print(f"Server listening on {server_socket.getsockname()}")
  38. # Loop forever
  39. while True:
  40.     try:
  41.         # Accept a new connection from a client
  42.         client_socket, client_address = server_socket.accept()
  43.         # Handle the client connection in a separate thread
  44.         threading.Thread(target=handle_client, args=(client_socket, client_address)).start()
  45.     except KeyboardInterrupt:
  46.         # Break the loop if the user presses Ctrl+C
  47.         break
  48. # Close the server socket
  49. server_socket.close()
  50. # Print the server address and port
  51. print(f"Server stopped on {server_socket.getsockname()}")


The program consists of two main parts: a function that handles each client connection, and a loop that accepts new connections and spawns new threads for each client.

The function `handle_client` takes two parameters: a client socket object and a client address tuple. The client socket object is used to send and receive data to and from the client, and the client address tuple contains the IP address and the port number of the client. The function prints the client address, and then enters a while loop that runs until the client closes the connection or an error occurs. Inside the loop, the function tries to receive data from the client, up to 1024 bytes at a time. If no data is received, the loop breaks. Otherwise, the function prints the received data, prepends "Server echo:" to the data, and sends it back to the client. The function also prints the sent data. If an exception occurs, the function prints the error message and breaks the loop. Finally, the function closes the client socket and prints the client address.


The main part of the program creates a TCP socket object using the `socket.socket` function, which takes two parameters: the address family and the socket type. The address family is `socket.AF_INET`, which means IPv4 addresses, and the socket type is `socket.SOCK_STREAM`, which means TCP sockets. The program then binds the socket to a local address and port using the `socket.bind` function, which takes a tuple as a parameter. The local address is "localhost", which means the same computer as the server, and the port is 8080, which is an arbitrary number that is not used by any other service. The program then listens for incoming connections using the `socket.listen` function, which takes a parameter that specifies the maximum number of connections in the queue. The program sets this parameter to 5, which means that the server can accept up to 5 connections at a time. The program then prints the server address and port using the `socket.getsockname` function, which returns a tuple containing the IP address and the port number of the socket.


The program then enters a while loop that runs forever, unless the user presses Ctrl+C to interrupt the program. Inside the loop, the program tries to accept a new connection from a client using the `socket.accept` function, which returns a tuple containing a new client socket object and a client address tuple. The program then calls the `handle_client` function in a separate thread using the `threading.Thread` function, which takes two parameters: the target function and the arguments for the function. The program passes the client socket object and the client address tuple as the arguments for the `handle_client` function. This way, the program can handle multiple clients simultaneously, without blocking the main thread. If the user presses Ctrl+C, the program catches the `KeyboardInterrupt` exception and breaks the loop. The program then closes the server socket and prints the server address and port.


Usage

To run the program, you need to save the code in a file with a .py extension, such as echo_server.py. Then, you need to open a terminal or a command prompt, and navigate to the directory where you saved the file. Then, you need to execute the following command:


python echo_server.py


This will start the server and print the server address and port, such as:

Server listening on ('127.0.0.1', 8080)


To connect to the server, you need to run a TCP socket client on another device, or on the same device using a different terminal or command prompt. You can use any TCP socket client that supports IPv4 addresses and TCP sockets, such as [netcat], [telnet], [PuTTY], etc. You need to specify the IP address and the port number of the server as the parameters for the client. For example, if you use netcat, you can execute the following command:

nc 127.0.0.1 8080


This will establish a connection to the server and print the server address and port, such as:

Connected to ('127.0.0.1', 8080)


Then, you can type any message you want and press Enter. The server will echo back your message with "Server echo:" prepended to it. For example, if you type "Hello, world!", the server will respond with "Server echo:Hello, world!". You can repeat this process as many times as you want. To close the connection, you can press Ctrl+C or type "exit" and press Enter. The server will print the client address and indicate that the connection is closed, such as:

Disconnected from ('127.0.0.1', 8080)


Testing

To test the functionality and performance of the TCP socket echo server, you can use various tools or methods, such as iperf, ping, traceroute, etc. These tools can help you measure the bandwidth, latency, jitter, packet loss, and other metrics of the TCP socket connection. You can also use different network conditions, such as different distances, speeds, loads, errors, etc., to see how the TCP socket echo server behaves under different scenarios. You can also modify the code to change the buffer size, the timeout, the error handling, and other parameters of the TCP socket echo server, and see how they affect the results.



In this article, I showed you how to write a simple TCP socket echo server in Python, which is a program that listens for incoming connections from TCP socket clients, and echoes back whatever data it receives from them. If you have any questions or feedback, please feel free to mail me or leave a comment below. Thank you for reading! 


email: tcpfast@gmail.com


Comments

Popular posts from this blog

How to Set Buffer Size for TCP Socket Programming in C++

TCP socket programming is a common way to communicate between different processes or machines over the network. However, one of the challenges of TCP socket programming is how to set the buffer size for sending and receiving data. The buffer size determines how much data can be stored in memory before it is transmitted or processed. If the buffer size is too small, the data may be fragmented or lost, resulting in poor performance or errors. If the buffer size is too large, the memory may be wasted or the data may be delayed, affecting the responsiveness or timeliness of the communication. In this blog post, I will explain how to set the buffer size for TCP socket programming in C++, and provide some examples of how to use the relevant functions and parameters. The buffer size for TCP socket programming in C++ can be set by using the setsockopt function, which allows the programmer to change the options for a socket. The setsockopt function has the following prototype: int setsockopt...

How to Capture and Modify TCP Packets Using Npcap Library in C

email:  tcpfast@gmail.com  In this blog post, I will show you how to use the pcap library in C to capture and modify TCP packets on the fly. The pcap library is a powerful tool for network analysis and manipulation, which allows you to access raw packets from various network interfaces. You can use the pcap library to implement your own network applications, such as firewalls, proxies, sniffers, etc. The Code The code I will use as an example is as follows: # include <stdio.h> # include <stdlib.h> # include <pcap.h> # include <Packet32.h> # include <ntddndis.h> # define MAX_PACKET_SIZE 65536 # define KEYWORD "keyword1" # define IP1 "192.168.0.1" # define PORT1 12345 void packet_handler (u_char* user_data, const struct pcap_pkthdr* pkthdr, const u_char* packet) ; int main () { pcap_t * handle; char errbuf[PCAP_ERRBUF_SIZE]; // Open the network adapter handle = pcap_open_live( "\\Device\\...