SSL套接字Python非阻塞

问题描述 投票:0回答:1

我在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()


非常感谢!

python-3.x multithreading sockets ssl nonblocking
1个回答
0
投票

最后我发现:该代码在ssl套接字+线程中工作正常。

唯一的错误是在我的server.py中:对于接收和发送,我只使用了一个线程。因此,每次我想发送东西时,我都会打开一个新线程。接收WHILE发送消息需要1个线程:]我的坏。

仍然感谢!

© www.soinside.com 2019 - 2024. All rights reserved.