'How to Solve Messaging, Leaving and Logging Problem

First, i ask a lot of questions i know it and i'm sorry... Anyway, i have a few problem on my Application.

I developed a TCP Chat Room with socket and thread modules. Everything is fine but when I write something I see it twice. I only want to see this once and like (ME : Message). Not only that, when I press CTRL + C I can't exit the application and even if I shut down the server, clients can message and the application stops. Finally, I want all messages from the user to be logged. How can I do that?

def broadcast(MESSAGE):
for CLIENT in CLIENT_LIST:
    CLIENT.send(MESSAGE)

def handle(CLIENT):
while True: 
    try:
        MESSAGE = CLIENT.recv(1024)
        broadcast(MESSAGE)
    except:
        INDEX = CLIENT_LIST.index(CLIENT)
        CLIENT.close()
        USERNAME = USERNAME_LIST[INDEX]
        broadcast (f'{USERNAME} Left The Chat!'.encode('utf-8'))
        USERNAME_LIST.remove(USERNAME)
        break

I will share my codes for you. I want learn it and solve with you. I know when i see a problem i'm writing here. Sorry, i'm writing there because i'm beginner so i'm a new in this world :)

import socket
import threading

HOST = "127.0.0.1"
PORT = 7777
ADDR = (HOST,PORT)

SERVER_SOCKET = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
SERVER_SOCKET.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
SERVER_SOCKET.bind((ADDR))
SERVER_SOCKET.listen()

CLIENT_LIST = []
USERNAME_LIST = []

def broadcast(MESSAGE):
    for CLIENT in CLIENT_LIST:
        CLIENT.send(MESSAGE)

def handle(CLIENT):
    while True: 
        try:
            MESSAGE = CLIENT.recv(1024)
            broadcast(MESSAGE)
        except:
            INDEX = CLIENT_LIST.index(CLIENT)
            CLIENT.close()
            USERNAME = USERNAME_LIST[INDEX]
            broadcast (f'{USERNAME} Left The Chat!'.encode('utf-8'))
            USERNAME_LIST.remove(USERNAME)
            break
            
def take():
    while True:
        CLIENT, ADDRESS = SERVER_SOCKET.accept()
        print(f'Connected With {str(ADDRESS)}')

        CLIENT.send("USERNAME".encode('utf-8'))
        USERNAME = CLIENT.recv(1024).decode('utf-8')
        USERNAME_LIST.append(USERNAME)
        CLIENT_LIST.append(CLIENT)

        print(f'Username Of The Client Is {USERNAME}!')
        broadcast(f'{USERNAME} Joined The Chat! Welcome!'.encode('utf-8)'))
        CLIENT.send("Connected To The Server!".encode('utf-8'))

        thread = threading.Thread(target=handle, args=(CLIENT, ))
        thread.start()

    print("Server Is Listening...")
    take()


Solution 1:[1]

Disclaimer: The following are direct solutions, but may not be the best design choice overall.

Seeing message twice:

The CLIENT sending MESSAGE is being broadcasted to again. Exclude sender from broadcast():

def broadcast(MESSAGE, sender):
    for CLIENT in CLIENT_LIST:
        if CLIENT == sender: continue
        CLIENT.send(MESSAGE)
...
broadcast(MESSAGE, CLIENT)

Threads not stopping with CTRL+C:

You can set daemon=True to stop the thread with the parent process, but read the warning here

thread = threading.Thread(target=handle, args=(CLIENT, ), daemon=True)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tony Liu