Post

Building a Chat Server and Client Using Python Socket Programming

Building a Chat Server and Client Using Python Socket Programming

Introduction

Real-time communication is a core feature of modern software systems, yet the low-level mechanisms that enable it are often hidden behind abstractions. Socket programming exposes these mechanisms directly, allowing developers to understand how data is transmitted between processes over a network.

In this post, I document the complete process of building a simple chat server and client using Python socket programming. The purpose of this project is educational: to understand client–server architecture, TCP communication, and basic concurrency using threads.


Prerequisites

Before starting, ensure the following requirements are met:

  • Python 3.x installed on the system
  • Basic familiarity with Python syntax
  • Introductory understanding of IP addresses and ports

No external libraries are required for this project.



Why Socket Programming?

Sockets form the foundation of network communication. Every web request, API call, or messaging service ultimately relies on socket-level interactions.

Working directly with sockets helps clarify:

  • How data flows between machines
  • The difference between connection-oriented and connectionless protocols
  • How servers handle multiple clients simultaneously
  • Why abstractions like HTTP and WebSockets exist

This project uses TCP sockets, which prioritize reliability and ordered delivery of data.


Project Setup

Create a new directory for the project and navigate into it:

1
2
mkdir chat_app
cd chat_app

The final project structure will be:

1
2
3
chat_app/
│── server.py
│── client.py

Understanding the Communication Model

This application follows a client–server model:

  • The server listens on a fixed IP address and port.
  • Clients initiate a connection to the server.
  • Communication occurs over TCP, which guarantees reliable and ordered data transmission.
  • Each client sends messages to the server, and the server responds to each message independently.

Implementing the Server

Importing Required Modules

Create a file named server.py and begin by importing the required modules:

1
2
import socket
import threading
  • socket enables low-level network communication
  • threading allows the server to handle multiple clients concurrently

Handling Client Communication

Define a function to manage communication with a connected client:

1
2
3
4
5
6
7
8
9
10
11
12
13
def handle_client(client_socket):
    while True:
        data = client_socket.recv(1024)
        if not data:
            break

        message = data.decode("utf-8")
        print(f"Received message: {message}")

        response = "Server received your message: " + message
        client_socket.sendall(response.encode("utf-8"))

    client_socket.close()

This function:

  • Continuously listens for incoming data
  • Detects client disconnection when no data is received
  • Sends a confirmation message back to the client
  • Closes the socket after communication ends

Starting the Server

Next, define the main server logic:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def main():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    host = "127.0.0.1"
    port = 12345

    server_socket.bind((host, port))
    server_socket.listen(5)

    print(f"Server listening on {host}:{port}")

    while True:
        client_socket, client_address = server_socket.accept()
        print(f"Accepted connection from {client_address}")

        client_thread = threading.Thread(
            target=handle_client,
            args=(client_socket,)
        )
        client_thread.start()

if __name__ == "__main__":
    main()

Key concepts used here:

  • AF_INET specifies IPv4 addressing
  • SOCK_STREAM specifies TCP
  • Each client connection is handled in a separate thread
  • The server runs continuously, accepting new connections

Implementing the Client

Client Code

Create a file named client.py and add the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import socket

def main():
    client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    host = "127.0.0.1"
    port = 12345

    client_socket.connect((host, port))

    while True:
        message = input("Enter message: ")
        client_socket.sendall(message.encode("utf-8"))

        data = client_socket.recv(1024)
        response = data.decode("utf-8")
        print("Server:", response)

if __name__ == "__main__":
    main()

The client:

  • Connects to the server using a known IP address and port
  • Sends user input as encoded bytes
  • Receives and displays the server’s response

Running and Testing the Application

Step 1: Start the Server

In one terminal window, run:

1
python server.py

The server will begin listening for incoming connections.

Step 2: Start One or More Clients

In separate terminal windows, run:

1
python client.py

Each client will connect to the server and allow message exchange.

Step 3: Test Concurrent Clients

Multiple clients can run simultaneously. Each client:

  • Maintains its own connection
  • Communicates independently with the server
  • Is handled in a separate thread on the server side

This demonstrates basic concurrency in networked systems.


Limitations of the Implementation

This project intentionally remains simple. Some limitations include:

  • Blocking socket operations
  • No message broadcasting between clients
  • No authentication or encryption
  • Limited scalability due to thread-per-client model

These constraints highlight why more advanced tools such as asyncio, WebSockets, or message brokers are used in production systems.


Key Takeaways

Through this project, the following concepts become concrete:

  • How TCP sockets establish and manage connections
  • How data is transmitted as bytes over a network
  • How servers handle multiple clients concurrently
  • Why abstraction layers exist in modern networking

Even a minimal implementation provides valuable insight into real-world network behavior.


Conclusion

Building a chat server and client using Python socket programming offers a clear view into the foundations of networked communication. By working directly with sockets, the mechanics behind everyday applications—such as messaging platforms and web services—become easier to understand.

This project serves as a strong starting point for exploring more advanced topics, including asynchronous networking, distributed systems, and real-time application design.

This post is licensed under CC BY 4.0 by the author.