From c314bc601b3abb08d6c844862e11e59809b5b4a7 Mon Sep 17 00:00:00 2001
From: Katharina <katharina.willig@outlook.com>
Date: Thu, 14 Nov 2024 22:08:09 +0100
Subject: [PATCH] add server and client with threads

---
 __pycache__/server.cpython-313.pyc | Bin 0 -> 2585 bytes
 clients.py                         |  32 ++++++++++
 server.py                          |  52 +++++++++++++++
 tcp_server.py                      |  98 -----------------------------
 udp_clients.py                     |  38 -----------
 5 files changed, 84 insertions(+), 136 deletions(-)
 create mode 100644 __pycache__/server.cpython-313.pyc
 create mode 100644 clients.py
 create mode 100644 server.py
 delete mode 100644 tcp_server.py
 delete mode 100644 udp_clients.py

diff --git a/__pycache__/server.cpython-313.pyc b/__pycache__/server.cpython-313.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b687e02c52c496945deeddac12b80431a6bd478f
GIT binary patch
literal 2585
zcmey&%ge>Uz`zinWR@Pl#=!6x#DQTpDC6@N1_p+y48aV+jNS}I5Sp=wF_@`{DVVv4
zIfg}vA($nGiH{+eHHMjw!I;IA5u#IpA%-Cc!bBmJK;mF~QG`LFJg6cdo+%TEWMC*_
zk6{lIgs_px7^WCz6DA}(*@J|U<socS2*selpwCdmrO!~r9n2=hP{b3=F2zv98_Xfa
zP{bF*r^J9zm(Hlk`4XhduZq*q$Xw4r&p^*GlldkCLzP5uYEfBgkwRv1i9$|haY<@k
zW?s5Nex5=VmqKD*ib6qtQHeq_G!#HaFt9K%FfcPPFno3Zhh;Qa5JU(wc!)4C<S~Xa
z27%;3LP$820pTxSF$M;11_g$622DmkO{QDy$vK&+c_qcSSc+5gQa}Q^sl~;K>8ZEa
zpfaF<Q&6}S>uePhTAW%`9Fv_`l93qWlAm0f3(^_mn^;_uS`_c%<Qn6WSzJ<-nN(Vm
znxYU~SzMBuTO3nRl%JKFToRLlkkc)O$`yk{K(C<k7H3jXequ^;VsS|kCj$e600RR<
zu>=DHLj%KoA;}K58ytN7+@0JL+^=!Sd}3x0mii3xA4=e`!UD&F5tPv67~~j28G?|5
z52S^GfgzX?794qu(eU63g^MaM_{uXdC^9H8M1ukxtSg8eOra2nV9jGfQVDWCiaG`c
zgh~aFo4C=W85ocfOf)?4hBAS?l*f$ZMrJ;SU?yXxAb#8?!2G7bfG{Zto12&sD&-l{
z8El#58PXUvnf+dZl35j>LQZO0i9$(6szP!`Vu>clEtaCx<T7yN6oG=}7Hei+N@~R|
zwxZPB{Ib+rtjRg~#i_SA^D>jO^AdAYi*K=|<|XH+q-wGhfda1xR1g&LF)%RP;()6G
z8Kj_~pismC5@*Xu%uC5hEfQg1U;yFbCU63{!NvE1iHlR{hKSU3?}^?EST2jGcDUc+
z5uK2Jg-7lqI|DcWj}IK|oI-bmB&X|6)Lp=KSxCLZ^$w44zh9@{46`ddN;i0f`h7Zm
zdi?H)%FQUfD5~1wafe5AhQti61$r0646ln>TokjoEM|3u$NCPB=ye{Mi##$jBChbL
z-Q*GcRSYU*nq?Fj7CM?aNiruRhdszspd|EJiV2eF5P1??PK1>UrA!PA1&q<4_ywC5
z%oq&{BQP705cwF4kxHac25iw7%oKztIU%Arlp%;0Y&;4P3{M33l2jg3G$=oUbz&<O
zLy=q=4T?D2Dv?SeB;T`yGNJl4S{!Ty0|Ns{CYaTjcwb^k>cMQpg;6x9zyVtvBn75W
z2qlJS8JIvQg9&3WyCqW|b0~9=JWLcp!{S+i!JW~Un}I=-!>@|pIX^EiH5pVimS>h^
zDBNQ4^K|wu0%i9qaX)CTQOHkIfRwx7YN1L%AuB&KFEs_85v#-z#+2lPg&~EgCetmp
zlEk9))RJ2)iACwfngX}jATqbu5|fit3rcRW78GUXmE2-3E-5MkCA}gc1_p*AP_nqi
zmXZp}t3{xi@fKTRK|yL>3OJjCGyE;il8mC%#FWgu^jmBpU?w<|-eN5-Nh~UX=I~qW
zi76>Xsl~-bpqld*8$?erY941VN=;79EK4m?VPIfT0+sS7!I}I47vCKTx%s>^d1v!?
z@^`S^;ozOXzl3>#`(mCMbr<;bu5jo-fYt$S(|srUPWHdTp>jh|e7f{R=@}uH1(mJ~
zYF-r7yez2Q!EuK}@H&UYMGlD>5?45s?r`w;^L6q~D7(TT_k@G@f`Ix8js;a0_>8V_
z7~kO#oDea=>w=u#1tI<GLS`3*%q|OAT;Z^U);AYKbgzq;Tof_6EMj(r!~6-q#C3l8
zOZ@Un$~J^;@Vv-x2dSBOI(d5dKFKn0^A~~23Qhi7Y{mJ>*{LN(ptNy|B_qGM<Q5C4
zJ};666?E*5Zt<Ret|7O$gZ-Vo<AXzjTpfLjBtcRvNtt;mx7Z-<0Z0sh;shKG;4lXV
z+)4(pMUY~X!zMRBr8Fniu1J@GfdN$E71uE^FnnNUWMsU}z<ZlP-~p>Z1IrCot_GHe
z46GM86c&gqU|W#2L1Y8l1vc|53>FXAdE0B7YA1wEkDC~`AndxT`9)Rp%j^~nY&RI#
z+PNFKJ3=Oybog9hkOc908+lv!A8>Fru;1X~Y2f_C!o(>1iGznx=#z{9qxeS^21brn
HPO$p`i@@FM

literal 0
HcmV?d00001

diff --git a/clients.py b/clients.py
new file mode 100644
index 0000000..5796a2c
--- /dev/null
+++ b/clients.py
@@ -0,0 +1,32 @@
+import socket
+import threading
+
+nickname=input("Choose a mickname: ")
+
+client=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+client.connect(('127.0.0.1', 55555))
+
+def receive():
+    while True:
+        try:
+            message=client.recv(1024).decode()
+            if message=='NICK':
+                client.send(nickname.encode())
+            else:
+                print(message)
+        except:
+            print("An error occured")
+            client.close()
+            break
+
+def write():
+    while True:
+        message=f'{nickname}: {input("")}'#as soon as user clicks enter and sends new input, we're asking for the next one, so either close client or send new messages
+        client.send(message.encode())
+
+#run receive and write threat
+receive_thread=threading.Thread(target=receive)
+receive_thread.start()
+
+write_thread=threading.Thread(target=write)
+write_thread.start()
\ No newline at end of file
diff --git a/server.py b/server.py
new file mode 100644
index 0000000..3023e87
--- /dev/null
+++ b/server.py
@@ -0,0 +1,52 @@
+import socket
+import threading
+
+host='127.0.0.1'
+port=55555
+
+print(f'Server ist listening on {host} and port {port}')
+
+server=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+server.bind((host, port))
+server.listen()
+
+clients=[]
+nicknames=[]
+
+def broadcast(message):
+    for client in clients:
+        client.send(message)
+
+def handle(client):
+    while True:
+        try:
+            message=client.recv(1024)
+            broadcast(message)
+        except:
+            index=clients.index(client)
+            clients.remove(client)
+            client.close()
+            nickname=nicknames[index]
+            broadcast(f'{nickname} left the chat'.encode())
+            nicknames.remove(nickname)
+            break
+
+def receive():
+
+    while True:
+        client, address=server.accept() #accept clients all the time
+        print(f"Connected with {str(address)}")
+
+        client.send('NICK'.encode()) #send to client keyword NICK
+        nickname=client.recv(1024).decode() #receive nickname from client
+        nicknames.append(nickname) #append nickname to list
+        clients.append(client) #append client to list
+
+        print(f'Nickname of client ist {nickname}')
+        broadcast(f'{nickname} joined the chat'.encode()) #broadcast to all clients connected to server
+        client.send("Connected to the server".encode()) #send to particular client that connection was successfull 
+
+        thread=threading.Thread(target=handle, args=(client,)) #start a thread, which handles the connection with this particular client
+        thread.start()
+
+receive()
\ No newline at end of file
diff --git a/tcp_server.py b/tcp_server.py
deleted file mode 100644
index bed7615..0000000
--- a/tcp_server.py
+++ /dev/null
@@ -1,98 +0,0 @@
-import socket
-import threading
-import multiprocessing
-import time
-import random
-
-# Konfigurationsparameter
-PORT = 5001  # TCP Port für Server
-BROADCAST_PORT = 5000  # UDP Port für Broadcast von Clients
-
-# Lock für die Leader-Wahl
-leader_lock = multiprocessing.Lock()
-leader_ip = None  # Globale Variable für die IP-Adresse des aktuellen Leaders
-
-def form_ring(members):
-    """Funktion zur Ringbildung für Server und Leader-Wahl."""
-    global leader_ip
-    leader_lock.acquire()
-    sorted_binary_ring= sorted([socket.inet_aton(member) for member in members])
-    sorted_ip_ring= [socket.inet_ntoa(node) for node in sorted_binary_ring]
-    return sorted_ip_ring
-
-def get_neighbour(ring, current_node_ip, direction='left'):
-    global leader_id
-    current_node_index= ring.index(current_node_ip) if current_node_ip in ring else -1
-    if current_node_index!= -1: 
-        if direction == 'left':
-            if current_node_index+ 1 == len(ring):
-             return ring[0]
-            else:
-             return ring[current_node_index+ 1]
-        else:
-            if current_node_index== 0: 
-             return ring[len(ring) -1]
-            else:
-             return ring[current_node_index-1]
-    else:
-        return None
-    
-
-def handle_client_connection(client_socket, client_address):
-    """Verarbeitung der Nachrichten von Clients."""
-    print(f"Verbindung vom Client {client_address} akzeptiert.")
-    while True:
-        try:
-            message = client_socket.recv(1024).decode()
-            if message:
-                print(f"Nachricht vom Client {client_address}: {message}")
-                client_socket.sendall(f"Empfangen vom Leader: {message}".encode())
-        except ConnectionError:
-            break
-    client_socket.close()
-
-def start_tcp_server(server_ip, server_address, members):
-    """Startet den TCP-Server und verarbeitet Verbindungen."""
-    global leader_ip
-    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    ########zeile nur wegen 0.0.0.0 später entfernen !!!!! für reuse adrr
-    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
-
-    server_socket.bind(server_address)
-    server_socket.listen()
-    print(f"Server {server_ip} hört auf {server_address}")
-
-    if leader_ip is None:
-        form_ring(members)  # Initiale Leader-Wahl
-
-    while True:
-        client_socket, client_address = server_socket.accept()
-        process = threading.Thread(target=handle_client_connection, args=(client_socket, client_address))
-        process.start()
-
-def server_process(server_ip, server_address, members):
-    """Prozess für jeden Server."""
-    start_tcp_server(server_ip, server_address, members)
-
-if __name__ == "__main__":
-    # Beispiel-Server IP-Adressen (zum Testen) mit 0.0.0.0, für Netzwerk mit IP-Adressen!!!!!!!!!!!!!!!!
-    members = ['0.0.0.0', '0.0.0.0', '0.0.0.0']
-    #servers = ['192.168.1.1', '192.168.1.2', '192.168.1.3']  # Hier IP-Adressen der Server eintragen
-    #server_addresses = [(ip, PORT) for ip in servers] !!!!!!!!!!!
-    server_addresses = [('0.0.0.0', PORT) for ip in members]
-    #members = ['192.168.0.1', '130.234.204.2', '130.234.203.2', '130.234.204.1', '182.4.3.111'] 
-    ######ring formation######
-    ring = form_ring(members)
-    print(ring)
-    neighbour= get_neighbour(ring, '0.0.0.0', 'left')
-    print(neighbour)
-
-    # Starte jeden Server als separaten Prozess
-    processes = []
-    for server_ip, server_address in zip(members, server_addresses):
-        process = multiprocessing.Process(target=server_process, args=(server_ip, server_address, members))
-        process.start()
-        processes.append(process)
-
-    for process in processes:
-        process.join()
\ No newline at end of file
diff --git a/udp_clients.py b/udp_clients.py
deleted file mode 100644
index ff8a238..0000000
--- a/udp_clients.py
+++ /dev/null
@@ -1,38 +0,0 @@
-import socket
-import time
-import threading
-
-def udp_broadcast_client(message, broadcast_address='255.255.255.255', port=5000):
-    """Sendet eine Broadcast-Nachricht an alle Server."""
-    client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
-    client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
-
-    while True:
-        client_socket.sendto(message.encode(), (broadcast_address, port))
-        print(f"Broadcast gesendet: {message}")
-        time.sleep(3)  # Nachrichten alle 3 Sekunden senden
-
-def receive_responses(port=5001):
-    """Empfängt Antworten vom Leader."""
-    response_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    response_socket.bind(("", port))
-    response_socket.listen()
-
-    while True:
-        conn, addr = response_socket.accept()
-        response = conn.recv(1024).decode()
-        print(f"Antwort vom Server erhalten: {response}")
-        conn.close()
-
-if __name__ == "__main__":
-    # Starte den Broadcast-Client und empfange die Server-Antworten in separaten Threads
-    message = "Hallo, ich bin ein Client!"
-    
-    broadcast_thread = threading.Thread(target=udp_broadcast_client, args=(message,))
-    response_thread = threading.Thread(target=receive_responses)
-
-    broadcast_thread.start()
-    response_thread.start()
-
-    broadcast_thread.join()
-    response_thread.join()
\ No newline at end of file
-- 
GitLab