ich bin neu hier und erhoffe mir etwas Rat von euch (ebenso ein Beginner was programming angeht).
Ich möchte eine stabile Client-Server-Kommunikation mit Python3 via Sockets und Multithreading aufbauen. Diese ist SSL-verschlüsselt. Soweit funktioniert auch alles, versuche alle möglichen Exceptions/Tracebacks abzufangen (zumindest bisher im Client-Script), aber wenn ich eine Clientverbindung beende, dreht der Server völlig durch und produziert ungewollte Ausgaben mit dem Fehler "Pipe broken". Das Serverscript stürzt dann auch irgendwann ab, und ich möchte, dass es sich quasi selbst wieder neu startet, wenn es abgestürzt ist oder nicht mehr stable läuft...
Die Kommunikation läuft auf Debian, und für die Erstellung eines eigenen openssl Zertifikats ist folgendes zu beachten:
Vielen Dank schonmal für eure Hilfe!openssl req -new -days 999 -newkey rsa:4096bits -sha512 -x509 -nodes -out server.crt -keyout server.key
Note: CN (Common Name) has to be the server adress (e.g. IP)
Don't forget to change rights for server.crt and server.key (chmod -v 777 server.crt and chmod -v 777 server.crt)
LG, Finux
Hier mein bisheriger unbeschnittener Code:
server.py:
Code: Alles auswählen
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::#
#:::::::::::::::::: MULTITHREAD + SSL ::::::::::::::::::#
#::::::::::::::::::::::::::: [ server.py ] ::::::::::::::::::::::::::#
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::#
#TODO: Checkausgabe für Socketbinding, Try-Excepts, Funktionen (z.B. Uhrzeit), OOP
import socket
import ssl
from _thread import *
host = '127.0.0.1'
port = 4100
max_connections = 2
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile="/home/finux/server.crt", keyfile="/home/fin/server.key")
socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket.bind((host, port))
socket.listen(max_connections)
def i_manage_client(connstream, client_socket, addr): # Function to manage clients
connstream.send(b'Server accepted the connection!')
while True:
data = connstream.recv(4096)
data = data.decode()
#print(data.encode('utf-8').hex())
print("Client {}: ".format(addr), data)
if data == "exit":
print("+++++ SOCKET CLOSED ++++")
socket.close()
try:
connstream.send(b'Servertestmessage')
except BrokenPipeError as e:
print(e)
print("MESSAGE COULD NOT BE SEND!")
socket.close()
try:
while True:
client_socket, addr = socket.accept()
connstream = context.wrap_socket(client_socket, server_side=True)
start_new_thread(i_manage_client, (connstream, client_socket, addr))
except (KeyboardInterrupt, OSError) as e:
print(e)
socket.close()
Hier dann die client.py:
Code: Alles auswählen
#::::::::::::::::::::::::::::::::::#
#:::: MULTITHREAD + SSL ::::#
#:::::::::: [ client.py] ::::::::::#
#::::::::::::::::::::::::::::::::::#
#TODO: "Funktionen", OOP
import socket, ssl, pprint, sys
from _thread import *
import time
global msg
msg = ''
ip = '127.0.0.1'
port = 4100
context = ssl.SSLContext()
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
try:
context.load_verify_locations("/home/finux/server.crt")
print("***CHECK- Certificate loading successful")
except (FileExistsError, FileNotFoundError) as e:
print(e)
print("::::: Program will be closed now! :::::")
sys.exit()
try:
# with socket.create_connection((ip, port)) as s:
conn = context.wrap_socket(socket.socket(socket.AF_INET, socket.SOCK_STREAM), server_hostname="127.0.0.1")
print("***CHECK- Socket only supports ssl connection successful")
conn.connect((ip, port))
print("***CHECK- Connection to server successful")
conn.send(b"Thanks for accepting the connection!")
print("***CHECK- Bytestring sending successful")
except ssl.CertificateError as e:
print("Hostname doesn't match.")
print("::::: Program will be closed now! :::::")
sys.exit()
except ConnectionError as e:
print(e)
print("::::: Program will be closed now! :::::")
sys.exit()
def msg_receive(conn, ip):
try:
while True:
server_answer = conn.recv(4096)
msg = server_answer.decode()
if msg != '':
print("\n[{}]: {}".format(ip, msg))
time.sleep(0.000001)
except OSError as e:
return 0
def msg_print_send(conn, ip):
while True:
message = input("\nNachricht: ")
if message != '':
conn.send(message.encode())
if message == 'exit':
print("+++++ SOCKET CLOSED ++++")
conn.close()
sys.exit()
break
return 0
start_new_thread(msg_receive, (conn, ip))
start_new_thread(msg_print_send, (conn, ip))
try:
while 1: # wieso muss die while-Schleife hier hin, damit das Script wie gewollt funktioniert???
pass
except KeyboardInterrupt as e:
print(e)