# Python Chat Server

This guide demonstrates how to build a simple TCP chat room. It consists of a **Server** that handles connections and broadcasts messages, and a **Client** that connects to the server to send and receive messages.

**Modules Used:**
*   [[programming/python/modules/socket-module|socket]]: To establish TCP connections.
*   `threading`: To handle multiple clients simultaneously on the server, and to send/receive simultaneously on the client.

## The Server Code

The server listens for incoming connections. When a client connects, the server starts a new thread to handle that specific client's messages while continuing to listen for new connections.

Save this as `server.py`.

```python
import socket
import threading

# Connection Data
HOST = '127.0.0.1' # Localhost
PORT = 55555

# Starting Server
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((HOST, PORT))
server.listen()

# Lists For Clients and Their Nicknames
clients = []
nicknames = []

def broadcast(message):
    """Sends a message to all connected clients."""
    for client in clients:
        client.send(message)

def handle(client):
    """Handles messages from a specific client."""
    while True:
        try:
            # Broadcasting Messages
            message = client.recv(1024)
            broadcast(message)
        except:
            # Removing And Closing Clients
            index = clients.index(client)
            clients.remove(client)
            client.close()
            nickname = nicknames[index]
            broadcast(f'{nickname} left!'.encode('ascii'))
            nicknames.remove(nickname)
            break

def receive():
    """Accepts new connections."""
    while True:
        client, address = server.accept()
        print(f"Connected with {str(address)}")

        # Request And Store Nickname
        client.send('NICK'.encode('ascii'))
        nickname = client.recv(1024).decode('ascii')
        nicknames.append(nickname)
        clients.append(client)

        print(f"Nickname is {nickname}")
        broadcast(f"{nickname} joined!".encode('ascii'))
        client.send('Connected to server!'.encode('ascii'))

        # Start Handling Thread For Client
        thread = threading.Thread(target=handle, args=(client,))
        thread.start()

print("Server is listening...")
receive()
```

## The Client Code

The client needs two threads: one to listen for incoming messages from the server (so it doesn't freeze waiting for input) and one to handle user input.

Save this as `client.py`.

```python
import socket
import threading

nickname = input("Choose your nickname: ")

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 55555))

def receive():
    """Listens for messages from the server."""
    while True:
        try:
            message = client.recv(1024).decode('ascii')
            if message == 'NICK':
                client.send(nickname.encode('ascii'))
            else:
                print(message)
        except:
            print("An error occurred!")
            client.close()
            break

def write():
    """Sends messages to the server."""
    while True:
        message = f'{nickname}: {input("")}'
        client.send(message.encode('ascii'))

# Starting Threads For Listening And Writing
receive_thread = threading.Thread(target=receive)
receive_thread.start()

write_thread = threading.Thread(target=write)
write_thread.start()
```

## Usage

1.  **Start the Server:**
    Open a terminal and run:
    ```bash
    python server.py
    ```

2.  **Start Clients:**
    Open multiple new terminal windows (one for each user) and run:
    ```bash
    python client.py
    ```

3.  **Chat:**
    Type messages in the client windows. They will appear in all other connected clients.

[[programming/python/python]]