尝试在套接字中发送和接收消息时发生异常

时间:2020-02-26 20:46:55

标签: python sockets encryption

我正在尝试建立一个使用RSA作为加密算法的加密聊天,服务器正在等待一个客户端,然后在建立连接时,我尝试同时运行这两种方法。 (接收和发送消息)。

我的问题是,当我运行该程序时,出现错误,表明我认为该连接已关闭。我已经尝试解决这个问题很长时间了,但不知道为什么会发生。

错误:

客户端:尝试对非套接字的对象进行操作

服务器端:已建立的连接被主机中的软件中止了

服务器端:

import socket
from threading import Thread
from time import sleep
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP

behavior = ['fuck', 'idiot', 'stupid', 'bitch', 'noob',
            'butt', 'penis', 'jerk', 'vagina', 'asshole',
            'dumbass', 'whorebag', 'nutsack', 'motherfucker',
            'bitch', 'shit', 'whore', 'boner', 'dipshit',
            'fuckoff', 'dipshit', 'lardass', 'pissed off',
            'shitfaced', 'douchebag']

def main_text():
    print("""    
\t███╗   ██╗██╗   ██╗██╗  ██╗███████╗
\t████╗  ██║██║   ██║██║ ██╔╝██╔════╝
\t██╔██╗ ██║██║   ██║█████╔╝ █████╗  
\t██║╚██╗██║██║   ██║██╔═██╗ ██╔══╝  
\t██║ ╚████║╚██████╔╝██║  ██╗███████╗
\t╚═╝  ╚═══╝ ╚═════╝ ╚═╝  ╚═╝╚══════╝
\tNuke - RSA Encrypted Chat | Roi Levi
""")

class EncryptedChat:
    def __init__(self, username):
        self.username = username.title()
        self.key = RSA.generate(1024) # private_key
        self.public_key = self.key.publickey() # pub_key
        self.token_decryptor  = PKCS1_OAEP.new(self.key)
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as self.sock:
            self.sock.bind(('0.0.0.0', 21513))
            self.sock.listen(1)
            print(f'\n\tHey, {self.username}. Waiting for Client: ')
            self.conn, self.addr = self.sock.accept()
            if self.conn:
                print(f'\n\t{self.addr[0]}:{self.addr[1]} Has Connected to the party!\n')
                Thread(target=self.send_msg).start()
                Thread(target=self.recv_msg).start()

    def send_msg(self) -> None:
        ip_address = socket.gethostbyname(socket.gethostname())
        while True:
            user_message = input(f'\t{self.username}@{ip_address}: ').encode()
            if user_message.decode().lower() in behavior:
                print('\n\tDo not curse other people, Banned for 30 seconds!')
                sleep(30)
            else:
               self.user_public_key = RSA.importKey(self.conn.recv(1024))
               self.token = PKCS1_OAEP.new(self.user_public_key)
               cipher_text = self.token.encrypt(user_message)
               self.conn.send(cipher_text)

    def recv_msg(self) -> None:
        while True:
            self.conn.send(self.public_key.exportKey())
            cipher_msg = self.conn.recv(1024)
            plain_text = self.token_decryptor.decrypt(cipher_msg)
            print(f'\tRecveived: {plain_text.decode()}')

main_text()
your_username = input('\n\tEnter Username: ')
if your_username in behavior:
    raise ValueError('\n\tInvalid Username, Do not use curse as username!')
else:
    if __name__ == '__main__':
        try:
            EncryptedChat(your_username)
        except KeyboardInterrupt:
            print('\n\tThank you for using our software, Good Bye!')

客户端:

import socket
from time import sleep
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from threading import Thread

behavior = ['fuck', 'idiot', 'stupid', 'bitch', 'noob',
            'butt', 'penis', 'jerk', 'vagina', 'asshole',
            'dumbass', 'whorebag', 'nutsack', 'motherfucker',
            'bitch', 'shit', 'whore', 'boner', 'dipshit',
            'fuckoff', 'dipshit', 'lardass', 'pissed off',
            'shitfaced', 'douchebag']

def main_text():
    print("""    
\t███╗   ██╗██╗   ██╗██╗  ██╗███████╗
\t████╗  ██║██║   ██║██║ ██╔╝██╔════╝
\t██╔██╗ ██║██║   ██║█████╔╝ █████╗  
\t██║╚██╗██║██║   ██║██╔═██╗ ██╔══╝  
\t██║ ╚████║╚██████╔╝██║  ██╗███████╗
\t╚═╝  ╚═══╝ ╚═════╝ ╚═╝  ╚═╝╚══════╝
\tNuke - RSA Encrypted Chat | Roi Levi
""")

class Client:
    def __init__(self, username):
        self.username = username.title()
        self.key = RSA.generate(1024)
        self.public_key = self.key.publickey()
        self.token_decryptor  = PKCS1_OAEP.new(self.key)
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as self.sock:
            self.sock.connect((socket.gethostname(), 21513))
            Thread(target=self.send_msg).start()
            Thread(target=self.recv_msg).start()

    def send_msg(self) -> None:
        ip_address = socket.gethostbyname(socket.gethostname())
        while True:
            user_msg = input(f'\t{self.username}@{ip_address}: ').encode()
            if user_msg.decode().lower() in behavior:
                print('\n\tDo not curse other people, Banned for 30 minutes.')
                sleep(30)
            else:
                self.user_public_key = RSA.importKey(self.sock.recv(1024))
                self.token = PKCS1_OAEP.new(self.user_public_key)
                cipher_text = self.token.encrypt(user_msg)
                self.sock.send(cipher_text)

    def recv_msg(self) -> None:
        while True:
            self.sock.send(self.public_key.export_key())
            cipher_msg = self.sock.recv(1024)
            plain_text = self.token_decryptor.decrypt(cipher_msg)
            print(f'\tRecveived: {plain_text.decode()}')

main_text()
your_username = input('\n\tEnter Username: ')
if your_username in behavior:
    raise ValueError('\tDo not use curse as your username!')
else:
    if __name__ == '__main__':
        try:
            Client(your_username)
        except KeyboardInterrupt:
            print('\n\tThank you for using our software, Good Bye!')

1 个答案:

答案 0 :(得分:1)

def __init__(self, username):
    ...
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as self.sock:

当您离开with ...块时,套接字将立即获得,如以下示例所示:

import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    print("inside",s)
print("outside",s)

此结果

inside <socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('0.0.0.0', 0)>
outside <socket.socket [closed] fd=-1, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0>
                       ^^^^^^^^

如您所见,套接字在with ...块外部关闭。因此,在self.socksend_msg内对recv_msg进行的任何操作都将失败,并显示“试图对不是套接字的对象进行操作”

因此,不要使用with ...而是

def __init__(self, username):
    ...
    self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    self.sock.connect((self.sock.gethostname(), 21513))
    ...

除了在某些情况下您甚至没有使用self.sock,而是错误地使用socket。例如,在这种情况下:

def send_msg(self) -> None:
    ip_address = socket.gethostbyname(socket.gethostname())