in meiner aktuellen client-server kommunikation fiel mir (leider gerade erst) ein problem auf..
während ich beim client daten erhalte, bin ich nicht in der lage irgendetwas an den server rauszusenden... ich dachte eigentlich, dass ich diesen umstand mit 2 eigenen threads (1 zum empfangen, 1 zum senden) gelöst hätte, aber ich bekomme dann folgende meldung:
"Unhandled exception in thread started by <function msg_print_send at 0x7f48d54219d8>
Traceback (most recent call last):
File "/home/fin/PycharmProjects/CSK/CSK_client2.py", line 41, in msg_print_send
conn.send(message.encode("utf-8"))
File "/usr/lib/python3.5/ssl.py", line 869, in send
return self._sslobj.write(data)
File "/usr/lib/python3.5/ssl.py", line 594, in write
return self._sslobj.write(data)
ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:1949)"
kurze infos zu der kommunikation:
- server.py soll auf einem kleinen (mir unbekannten, bs: debian) gerät (außer landes) laufen
- server.py soll viele clients zur gleichen zeit bedienen können
- die verbindung ist ssl + sha512 verschlüsselt
(kurzinfo zur erstellung eines eigenen ssl zertifikats unter debian: 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))
- client.py werde ich bald in eine html einbinden
- client.py soll einen dauerhaften datenstrom vom server empfangen können, diesen aber auch mit einem einfachen befehl stoppen (verbindung zum server soll erhalten bleiben) dürfen
- client.py soll während dem empfangen eines datenstroms in der lage sein zeitgleich strings an den server zu senden
ich hoffe das reicht an infos, sry wenn ich was vergessen habe. dass einiger unsinn noch im code rumgeistert ist mir klar, und wird noch behoben
@__blackjack__ : _thread werde ich bald durch das modul threading tauschen, ich habe deine worte noch im hinterkopf!
hier mein bisheriger code:
server.py
Code: Alles auswählen
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::#
#:::::::::::::::::::::::::::::::::::: MULTITHREAD + SSL ::::::::::::::::::::::::::::::::::::::::::#
#::::::::::::::::::::::::::::::::::::::::::::: [ server.py ] ::::::::::::::::::::::::::::::::::::::::::::::::::#
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::#
#TODO: logs, try-exp
import socket as socketlib
import ssl
from _thread import *
from time import ctime
import logging
import sys
import time
host = '127.0.0.1'
port = 4500
max_connections = 2
logging.basicConfig(filename="log.log", level=logging.DEBUG,
format='[%(levelname)s] %(asctime)s - %(name)s : - LINE_%(lineno)s (%(funcName)s) # PROCESS ID %(process)s >>> THREAD ID %(thread)s\n || %(message)s \n')
def manage_client(connstream, client_socket, addr):
print("~~ Step 6/6 successful [Server started admitted request in new thread (Client {})] ~~".format(addr))
logging.debug("~~ Step 6/6 successful [Server started admitted request in new thread (Client %s)] ~~", addr)
connstream.send(b'Server accepted the connection!')
usr_accepted = False
while True:
data = connstream.recv(4096)
data = data.decode("utf-8")
print("Client {}: ".format(addr), data)
logging.debug("Client %s: %s", addr, data)
if data == '' or data == 'exit':
disconnect(connstream, addr)
break
elif data == "show status":
if usr_accepted == True:
show_status(connstream)
elif data == "username":
usr_accepted = authentification(connstream, addr)
if usr_accepted == False:
disconnect(connstream, addr)
break
continue
elif data == "count":
for i in range(1, 61):
connstream.send(str(i).encode("utf-8"))
time.sleep(1)
try:
connstream.send(b'Servertestmessage')
pass
except BrokenPipeError as e:
print(e)
logging.debug(e)
logging.exception('Got exception here')
print("MESSAGE COULD NOT BE SEND!")
logging.debug("MESSAGE COULD NOT BE SEND!")
connstream.close()
break
def authentification(connstream, addr):
auth_dict = {'fin':'finja', 'haxe':'1337', 'hell':'d404559f602eab6fd602ac7680dacbfaadd13630335e951f097af3900e9de176b6db28512f2e000b9d04fba5133e8b1c6e8df59db3a8ab9d60be4b97cc9e81db'}
auth_data_usr = connstream.recv(4096)
auth_data_usr = auth_data_usr.decode("utf-8")
for usr_data in auth_dict:
if auth_data_usr == usr_data:
auth_data_pwd = connstream.recv(4096)
auth_data_pwd = auth_data_pwd.decode("utf-8")
if auth_dict[usr_data] == auth_data_pwd:
connstream.send(b'Authentification succeeded!')
print("CLIENT AUTHENTIFICATION FROM {} ACCEPTED".format(addr))
logging.debug("CLIENT AUTHENTIFICATION FROM {} ACCEPTED".format(addr))
return True
else:
connstream.send(b'Authentification failed!')
print("CLIENT AUTHENTIFICATION FROM {} NOT ACCEPTED".format(addr))
logging.debug("CLIENT AUTHENTIFICATION FROM {} NOT ACCEPTED".format(addr))
return False
def disconnect(connstream, addr):
print("+++++ SOCKET CLOSED +++++ [Client {}]".format(addr))
logging.debug("+++++ SOCKET CLOSED +++++ [Client {}]".format(addr))
connstream.close()
def show_status(connstream):
server_location_time = ctime()
connstream.send(server_location_time.encode("utf-8"))
connstream.send("Location: CHINA".encode("utf-8"))
connstream.send("Adress: XYZ".encode("utf-8"))
connstream.send("Last update: Oct-11-2019".encode("utf-8"))
connstream.send("Python Version: 3".encode("utf-8"))
def main():
try:
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context.load_cert_chain(certfile="/home/fin/server.crt", keyfile="/home/fin/server.key")
print("~~ Step 1/6 successful [Loading ssl certification]~~")
logging.debug("~~ Step 1/6 successful [Loading ssl certification]~~")
except FileNotFoundError:
print("CERTIFICATE NOT FOUND!!")
logging.exception("Certificate could not be loaded. Program is not running anymore. Please restart the program!")
logging.error("Certificate could not be loaded. Program is not running anymore. Please restart the program!")
sys.exit()
try:
socket = socketlib.socket(socketlib.AF_INET, socketlib.SOCK_STREAM)
socket.bind((host, port))
print("~~ Step 2/6 successful [Socket Binding IP {} on PORT {} as IPv4] ~~".format(host, port))
logging.debug("~~ Step 2/6 successful [Socket Binding IP {} on PORT {} as IPv4] ~~".format(host, port))
except OSError as e:
print("Binding ip {} on port {} failed. Address already in use.".format(host, port))
logging.exception("Binding ip %s on port %s failed. Address already in use. Please restart the program!", host, port)
sys.exit()
socket.listen(max_connections)
print("~~ Step 3/6 successful [Server is listening for requests] ~~")
logging.debug("~~ Step 3/6 successful [Server is listening for requests] ~~")
while True:
try:
client_socket, addr = socket.accept()
print("~~ Step 4/6 successful [Server got a request from {}] ~~".format(addr))
logging.debug("~~ Step 4/6 successful [Server got a request from %s] ~~", addr)
try:
connstream = context.wrap_socket(client_socket, server_side=True)
print("~~ Step 5/6 successful [Request is ssl encrypted now (Client {})] ~~".format(addr))
logging.debug("~~ Step 5/6 successful [Request is ssl encrypted now (Client %s)] ~~", addr)
except ssl.SSLError as e:
print("Error {}: {}".format(e.args[0], e.args[1]))
logging.debug("Error {}: {}".format(e.args[0], e.args[1]))
print("Connection to {} closed.".format(addr))
logging.debug("Connection to {} closed.".format(addr))
continue
start_new_thread(manage_client, (connstream, client_socket, addr))
except KeyboardInterrupt as e:
logging.exception('Got exception on main handler')
if __name__ == "__main__":
main()
client.py
Code: Alles auswählen
#::::::::::::::::::::::::::::::::::#
#:::: MULTITHREAD + SSL ::::#
#:::::::::: [ client.py] ::::::::::#
#::::::::::::::::::::::::::::::::::#
#TODO: logs
import socket, ssl, pprint, sys
from _thread import *
import time
import hashlib
global msg
msg = ''
ip = '127.0.0.1'
port = 4500
def msg_receive(conn, ip):
try:
while True:
server_answer = conn.recv(4096)
msg = server_answer.decode("utf-8")
if msg != '':
print("\n[{}]: {}".format(ip, msg))
time.sleep(0.000001)
if msg == '':
print("LOST CONNECTION TO SERVER!")
print("TRYING TO RECONNECT... (Refresh Browser!)") #TODO:
#conn.close()
return 0
except OSError as e:
return 0
def msg_print_send(conn, ip):
while True:
message = input("\nNachricht: ")
conn.send(message.encode("utf-8"))
if message == 'username':
usr_message = input("\nBN: ")
conn.send(usr_message.encode("utf-8"))
pwd_message = hashlib.sha512(bytes(input("\nPW: "), "utf-8"))
p_message = (pwd_message.hexdigest())
conn.send(p_message.encode("utf-8"))
if message == 'exit':
print("+++++ SOCKET CLOSED +++++")
conn.close()
sys.exit() #TODO: skript beendet sich nicht
break
#if message != '':
#conn.send(message.encode("utf-8"))
return 0
def main():
context = ssl.SSLContext()
context.verify_mode = ssl.CERT_REQUIRED
context.check_hostname = True
try:
context.load_verify_locations("/home/fin/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")
try:
conn.connect((ip, port))
print("***CHECK- Connection to server successful")
conn.send(b"Thanks for accepting the connection!")
print("***CHECK- Bytestring sending successful")
except:
print("CONNECTION NOT POSSIBLE! IN 10 SECONDS TRYING TO CONNECT AGAIN..")
time.sleep(10.0)
return 0
except ssl.CertificateError as e:
# print("Error {}: {}".format(e.args[0], e.args[1]))
# print("Error {}:".format(e)) #TODO: Darf Ziel-IP bekannt sein? (Fehlerprovokation bei Hackern) SICHERHEITSMANGEL!
print("Hostname doesn't match.")
print("::::: Program will be closed now! :::::")
sys.exit()
except ConnectionError as e:
# print("Error {}: {}".format(e.args[0], e.args[1]))
print(e)
print("::::: Program will be closed now! :::::")
sys.exit()
start_new_thread(msg_receive, (conn, ip))
start_new_thread(msg_print_send, (conn, ip))
try:
while 1:
pass
except KeyboardInterrupt as e:
print(e)
if __name__ == "__main__":
main()