I'm working on a simple chat application using Python's socket programming and RSA encryption for secure communication. The application consists of two scripts: client.py and server.py. The server script handles incoming connections and forwards messages between clients, while the client script allows users to send and receive messages.
When I run two instances of client.py to simulate a chat session and start sending messages between them, the messages do not appear on the other client. Additionally, after sending two messages from the second client instance, I encounter the following error:
Exception in thread Thread-2 (write):
Traceback (most recent call last):
File "/opt/homebrew/Cellar/[email protected]/3.11.6_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/threading.py", line 1045, in _bootstrap_inner
self.run()
File "/opt/homebrew/Cellar/[email protected]/3.11.6_1/Frameworks/Python.framework/Versions/3.11/lib/python3.11/threading.py", line 982, in run
self._target(*self._args, **self._kwargs)
File "/Users/xxxxxx/client.py", line 35, in write
client.send(encrypted_message)
OSError: [Errno 9] Bad file descriptor
Here's a brief overview of how the client and server scripts handle communication:
- The client script generates RSA key pairs and exchanges public keys with the server.
- Messages sent from a client to the server are encrypted with the server's public key.
- The server then forwards these messages to other clients, encrypting the message with each receiving client's public key.
Server.py
import socket
import threading
import rsa
# Generate RSA keys for the server
server_public_key, server_private_key = rsa.newkeys(2048)
clients = []
client_public_keys = {}
def broadcast(message, sender_socket):
for client in clients:
if client != sender_socket: # Avoid sending the message back to the sender
client_public_key = client_public_keys[client]
encrypted_message = rsa.encrypt(message.encode(), client_public_key)
client.send(encrypted_message)
def handle_client(client):
while True:
try:
message = client.recv(1024)
broadcast(message, client)
except:
index = clients.index(client)
clients.remove(client)
client.close()
break
def receive():
host = '127.0.0.1'
port = 5551 # Example port, adjust as needed
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((host, port))
server.listen(2)
print(f'Server listening on {host}:{port}')
while True:
client, address = server.accept()
print(f"Connected with {str(address)}")
# Send server public key to client
client.send(server_public_key.save_pkcs1('PEM'))
# Receive client's public key
client_public_key_pem = client.recv(1024)
client_public_key = rsa.PublicKey.load_pkcs1(client_public_key_pem)
client_public_keys[client] = client_public_key
clients.append(client)
thread = threading.Thread(target=handle_client, args=(client,))
thread.start()
receive()
Client.py
import socket
import threading
import rsa
# Generate RSA keys for the client
client_public_key, client_private_key = rsa.newkeys(1024)
alias = input("Choose an alias: ")
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('127.0.0.1', 5551)) # Ensure this matches the server's IP and port
# Receive server's public key
server_public_key_pem = client.recv(1024)
server_public_key = rsa.PublicKey.load_pkcs1(server_public_key_pem)
# Send client's public key to server
client.send(client_public_key.save_pkcs1('PEM'))
def receive():
while True:
try:
message = client.recv(1024)
decrypted_message = rsa.decrypt(message, client_private_key).decode()
print(decrypted_message)
except:
print("An error occurred!")
client.close()
break
def write():
while True:
message = f'{alias}: {input("")}'
encrypted_message = rsa.encrypt(message.encode(), server_public_key)
client.send(encrypted_message)
receive_thread = threading.Thread(target=receive)
receive_thread.start()
write_thread = threading.Thread(target=write)
write_thread.start()
I'm looking for insights on why the messages are not being displayed to each other and why the second client instance throws a "Bad file descriptor" error after sending a couple of messages. Any advice on debugging this issue or suggestions on how to improve the communication flow would be greatly appreciated.