98 lines
3.2 KiB
Python
98 lines
3.2 KiB
Python
import socket
|
|
import threading
|
|
|
|
HOST = '127.0.0.1' # IP address for the server
|
|
PORT = 3000 # Port number for the server
|
|
MAX_CONNECTIONS = 10 # Maximum number of clients allowed to connect
|
|
|
|
# Dictionary to store connected clients and their nicknames
|
|
clients = {}
|
|
|
|
# Function to handle each client connection
|
|
|
|
|
|
def handle_client(conn, addr):
|
|
print(f"[NEW CONNECTION] {addr} connected.")
|
|
|
|
# Ask the client to set a nickname
|
|
nickname = conn.recv(1024).decode()
|
|
|
|
# Add the client to the dictionary of connected clients
|
|
clients[conn] = nickname
|
|
|
|
# Notify all other clients that a new client has joined the chat
|
|
broadcast(f"{nickname} has joined the chat!".encode())
|
|
|
|
while True:
|
|
# Receive message from the client
|
|
message = conn.recv(1024).decode()
|
|
if message:
|
|
# Check if the message is a private message to a specific client
|
|
if message == "\q":
|
|
# If the message is "quit", remove the client from the dictionary of connected clients
|
|
del clients[conn]
|
|
# Notify all other clients that the client has left the chat
|
|
broadcast(f"{nickname} has left the chat.".encode())
|
|
print(f"[DISCONNECTED] {addr} disconnected.")
|
|
# Close the client connection
|
|
conn.close()
|
|
break
|
|
elif message.startswith("@"):
|
|
recipient = message.split(" ")[0][1:]
|
|
message = message.split(" ", 1)[1]
|
|
send_private_message(conn, recipient, message)
|
|
else:
|
|
# Broadcast the message to all connected clients
|
|
broadcast(f"{nickname}: {message}".encode())
|
|
|
|
else:
|
|
# If message is empty, remove the client from the dictionary of connected clients
|
|
del clients[conn]
|
|
# Notify all other clients that the client has left the chat
|
|
broadcast(f"{nickname} has left the chat.".encode())
|
|
# Close the client connection
|
|
conn.close()
|
|
break
|
|
|
|
# Function to broadcast a message to all connected clients
|
|
|
|
|
|
def broadcast(message):
|
|
for client in clients:
|
|
client.sendall(message)
|
|
|
|
# Function to send a private message to a specific client
|
|
|
|
|
|
def send_private_message(sender_conn, recipient, message):
|
|
for client, nickname in clients.items():
|
|
if nickname == recipient:
|
|
client.sendall(
|
|
f"(Private) {clients[sender_conn]}: {message}".encode())
|
|
sender_conn.sendall(
|
|
f"(Private) {clients[sender_conn]}: {message}".encode())
|
|
break
|
|
|
|
|
|
# Create a socket object
|
|
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
|
# Bind the socket object to the specified host and port number
|
|
server_socket.bind((HOST, PORT))
|
|
|
|
# Listen for incoming connections
|
|
server_socket.listen(MAX_CONNECTIONS)
|
|
|
|
print(f"[LISTENING] Server is listening on {HOST}:{PORT}.")
|
|
|
|
while True:
|
|
# Accept incoming connections
|
|
conn, addr = server_socket.accept()
|
|
|
|
# Create a new thread to handle the client connection
|
|
thread = threading.Thread(target=handle_client, args=(conn, addr))
|
|
thread.start()
|
|
|
|
# Print the number of active connections
|
|
print(f"[ACTIVE CONNECTIONS] {threading.active_count() - 1}")
|