我在python3上进行了客户端-服务器通信。它运行良好,服务器可以服务多个客户端,所有服务器都具有openssl-import并使用线程。
[我现在想要的是:他们应该能够使用openSSL,并且在套接字(服务器和客户端)上接收某些内容时,它们应该能够在接收数据的同时发送一些内容(例如,从客户端调用'count',然后再键入该类型获取服务器时的其他答案)。但是,当我运行我的代码时,每次(在客户端接收时)我想发送一些东西时,它最终都会识别出我尝试发送的内容。很难解释(我的英语不是最好的)。我究竟做错了什么?我必须将所有套接字设置为“非阻塞模式”吗?也许您可以检查一下:
服务器:
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::#
#:::::::::::::::::::::::::::::::::::: MULTITHREAD + SSL ::::::::::::::::::::::::::::::::::::::::::#
#::::::::::::::::::::::::::::::::::::::::::::: [ server.py ] ::::::::::::::::::::::::::::::::::::::::::::::::::#
#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::#
#TODO: logs, try-exp
import socket as socketlib
import ssl
from threading import Thread
from time import ctime #formatiertes datetime nutzen!
import logging
import time
HOST = '127.0.0.1'
PORT = 4200
AUTHENTICATIONS = {'fin': 'finja',
'haxe': '1337',
'hell': 'd404559f602eab6fd602ac7680dacbfaadd13630335e951f097af3900e9de176b6db28512f2e000b9d04fba5133e8b1c6e8df59db3a8ab9d60be4b97cc9e81db'
}
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.sendall(b'Server accepted the connection!')
usr_accepted = False
while True:
data = connstream.recv(4096).decode("utf-8")
print("Client {}: ".format(addr), data)
logging.debug("Client %s: %s", addr, data)
if data == 'exit':
disconnect(connstream, addr)
break
elif data == "show status":
if usr_accepted:
show_status(connstream)
elif data == "username":
usr_accepted = authentication(connstream, addr)
if not usr_accepted:
disconnect(connstream, addr)
break
continue
elif data == "count":
for i in range(1, 10):
connstream.sendall(str(i).encode("utf-8"))
time.sleep(3)
try:
#connstream.sendall(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 authentication(connstream, addr):
usr_name = connstream.recv(4096).decode("utf-8")
usr_pwd = connstream.recv(4096).decode("utf-8")
if usr_name in AUTHENTICATIONS:
auth_pwd = AUTHENTICATIONS[usr_name]
if auth_pwd == usr_pwd:
connstream.send(b'Authentication succeeded!')
logging.debug("CLIENT AUTHENTICATION FROM {} ACCEPTED".format(addr))
return True
connstream.send(b'Authentication failed!')
logging.debug("CLIENT AUTHENTICATION 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.sendall(server_location_time.encode("utf-8"))
connstream.sendall("Location: CHINA".encode("utf-8"))
connstream.sendall("Adress: XYZ".encode("utf-8"))
connstream.sendall("Last update: Oct-11-2019".encode("utf-8"))
connstream.sendall("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!")
server_socket = socketlib.socket(socketlib.AF_INET, socketlib.SOCK_STREAM)
with server_socket:
server_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))
server_socket.listen()
print("~~ Step 3/6 successful [Server is listening for requests] ~~")
logging.debug("~~ Step 3/6 successful [Server is listening for requests] ~~")
try:
while True:
client_socket, addr = server_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)
client_socket = 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)
Thread(target=manage_client, args=(client_socket, server_socket, addr), daemon=True).start()
except KeyboardInterrupt as e:
print(e)
logging.exception(e)
if __name__ == "__main__":
main()
和客户:
#::::::::::::::::::::::::::::::::::#
#:::: 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 = 4200
def msg_receive(conn, IP):
try:
while True:
msg = conn.recv(4096).decode("utf-8")
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()
break
except OSError as e:
return
def msg_print_send(conn, IP):
while True:
message = input("\nNachricht: ")
conn.sendall(message.encode("utf-8"))
if message == 'username':
usr_message = input("\nBN: ")
conn.sendall(usr_message.encode("utf-8"))
pwd_message = hashlib.sha512(bytes(input("\nPW: "), "utf-8"))
p_message = (pwd_message.hexdigest())
conn.sendall(p_message.encode("utf-8"))
if message == 'exit':
print("+++++ SOCKET CLOSED +++++")
conn.close()
sys.exit() #TODO: skript beendet sich nicht
break
#if message != '':
#conn.sendall(message.encode("utf-8"))
#return
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.sendall(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
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
time.sleep(1)
except KeyboardInterrupt as e:
print(e)
if __name__ == "__main__":
main()
非常感谢!
最后我发现:该代码在ssl套接字+线程中工作正常。
唯一的错误是在我的server.py中:对于接收和发送,我只使用了一个线程。因此,每次我想发送东西时,我都会打开一个新线程。接收WHILE发送消息需要1个线程:]我的坏。
仍然感谢!