川师信安大作业

作业一 DH算法的不足与解决办法

        不足之处:DH算法没有提供双方身份得到任何信息,意味着双方无法验证对方的身份,容易遭受中间人攻击;其次算法时计算密集型,也就意味着会频繁地调用CPU,会更容易遭受阻塞性攻击,攻击者可以通过请求大量的密钥来使服务器方花费大量的计算资源。且没有办法防止重放攻击

        解决办法:可以通过结合数字证书的方法来抵御中间人攻击,步骤如下:

                A和B双方各自获取数字证书,并验证对方的数字证书是否合法。

                A和B双方使用数字证书中的公钥进行密钥交换。

                A和B双方使用交换后的密钥进行加密通信。

作业二 设计基于CHAP的登录认证模块

        本次实验使用的是socket通信将服务器和客户端同时部署在本机,前端使用HTML和CSS,后端使用MYSQL和Flask,登录认证模块使用CHAP挑战认证

        代码

        客户端

from flask import Flask, request, render_template
import socket
import hashlib
import logging



app = Flask(__name__)

# 与后端的地址和端口
address = ('127.0.0.1', 7766)

# 创建UDP客户端
udpclient = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
udpclient.bind(('127.0.0.1', 7788))

# 定义双方共有的f函数
def func_A_B(secret, password):
    return hashlib.sha256((secret + password).encode()).hexdigest()

# 定义路由和视图函数
@app.route('/',methods=['get', 'post'])
def index():

    return render_template("/info.html")

#调用验证函数
@app.route('/authenticate', methods=['POST'])
def authenticate():

    count = request.form['pwdPromt']
    print(count)
    password = request.form['pwd']
    print(password)

    udpclient.sendto(count.encode(), address)
    udpclient.sendto(password.encode(), address)

    info, addr = udpclient.recvfrom(1024)
    if info.decode() == "数据库匹配失败!":
        return "数据库匹配失败!"
    
    data, addr = udpclient.recvfrom(1024)
    secret_send = func_A_B(data.decode(), password)
    udpclient.sendto(secret_send.encode(), address)

    result, addr = udpclient.recvfrom(1024)
    if result.decode() == "0":
        return "认证失败!可能遭遇重放攻击"
    else:
        return render_template("/index.html")
        #返回认证成功页面

if __name__ == '__main__':
    app.run()

        服务器端

        


#服务器端 完成认证后将结果返回给客户端
import time
import socket
import random
import hashlib
import mysql.connector
#服务器端代码
udpserver = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
udpserver.bind(('127.0.0.1',7766))
address = ('127.0.0.1',7788)

#数据库查询账号是否存在
def database_connect(count):
    try:
        mydb = mysql.connector.connect(
            host="localhost",
            port = 3306,
            user="root",
            password="030704",
            database = "user",
            charset = 'utf8'
        )

        cursor = mydb.cursor()
        qu = "select * from user.user where id = %s"
        cursor.execute(qu,(count,))
        for row in  cursor.fetchall():
            username = row[0]
            password = row[1]
        return username,password

    except mysql.connector.Error as err:
        print(f"Something went wrong: {err}")
    else:
        print("MySQL connection is OK.")


#生成64位随机数
def generate_64bit_random():
    bits = ""
    for _ in range(64):
        bits += str(random.randint(0, 10))
    return int(bits, 10)


#定义双方共有的f函数
def func_A_B(secret,password):
    return hashlib.sha256((secret+password).encode()).hexdigest()




if __name__ == '__main__':
    while True:
        count, addr = udpserver.recvfrom(1024)
        password, addr = udpserver.recvfrom(1024)
        # print(database_connect(count))

        #判断账号密码是否正确
        if database_connect(count):
            #返回从数据库查找到的账号密码
            count, key = database_connect(count)

            #返回数据库查询结果
            udpserver.sendto("数据库匹配成功".encode(),address)

            #生成随机数
            secret = generate_64bit_random()
            print(secret)
            udpserver.sendto(str(secret).encode(),address)


            # 判断客户端返回的随机数和密码Hash是否与本地匹配
            secret_password_hash = func_A_B(str(secret),key)
            print("本地生成的Hash值为 %s" % secret_password_hash)
            hash_return,addr = udpserver.recvfrom(1024)
            print("从客户端返回的Hash值为 %s" % hash_return.decode())
            if hash_return.decode() == str(secret_password_hash):
                udpserver.sendto("------------------------认证成功!------------------------".encode(),address)
                print(time.ctime(time.time())+"\n"+"--------------------认证完成---------------------------------------------")
            else:
                udpserver.sendto("0".encode(),address)


        else:
            udpserver.sendto("数据库匹配失败!".encode(),address)

        效果展示

        当客户端尝试在页面登录时,输入账号和密码如下所示

        

2021110145 彭正武

        此时前端将用户输入的账号和密码发送给后端,后端通过检测账号是否存在返回一个数据库查询结果(查询数据库中的账号和密码),这一步是返回用户是否存在;

        然后服务器生成一个64位的随机数,并将其发送给客户端。客户端在本机将密码和随机数通过哈希函数运算后,将运算结果返回给后端

        后端将随机数和第一步查询到的密码进行哈希函数运算后,将运算结果同客户端返回的哈希函数值作比较,如果相同则挑战认证成功。如果两者不同,则说明认证失败,可能遭受了重放攻击;后端的验证如下所示

川师信安大作业_第1张图片

     

        登录认证成功的页面

        

2021110145 彭正武

        登录认证失败的页面

        

川师信安大作业_第2张图片 2021110145 彭正武

      

        

作业三 SSL和IKE协议过程

        SSL协议

        川师信安大作业_第3张图片

 川师信安大作业_第4张图片

川师信安大作业_第5张图片

川师信安大作业_第6张图片

川师信安大作业_第7张图片

川师信安大作业_第8张图片

        IKE

川师信安大作业_第9张图片

川师信安大作业_第10张图片

川师信安大作业_第11张图片

作业四 为正在开发的系统部署PGP安全通信模块

        要求:保证真实性,完整性,不可否认性和保密性

        本实验使用socket通信系统部署在本机,发送方与接收方同时使用本地环回地址+不同端口号进行通信

         客户端,用户在发送完对话后的效果如下所示:

        首先会计算对话的Hash值,然后使用私钥对Hash值进行签名得到MAC,然后将明文与MAC拼接在一起(同时还拼接了发送消息时的时间戳)。拼接完成后进行压缩,对整个拼接内容使用ECB一次一密的方式传输加密内容,然后使用服务器端的RSA公钥加密,再转码为base64传送到服务器端

川师信安大作业_第12张图片

        服务器端接收到密文后,首先会解码,然后根据自己的RSA私钥解密提取压缩数据,然后解压缩,再利用ECB解密,得到明文与MAC,可以通过正则表达式分离出明文和Hash值,通过计算明文的Hash值与传输的Hash值是否相同来验证是否遭遇了攻击

川师信安大作业_第13张图片

        模拟代码,客户端

import re
#部署在本地的客户端

import socket
import time
import threading
import hashlib
import random
import base64
import string
import chardet
import rsa


from Crypto.Cipher import AES, PKCS1_OAEP

from cryptography.hazmat.primitives.asymmetric import rsa,padding
from cryptography.hazmat.primitives import serialization,hashes
from cryptography.hazmat.backends import default_backend

udpclient = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
udpclient.bind(('127.0.0.1',8888))


#AES加密时位数不够时填充 接收时去除填充块的方法
pad = lambda s: s + chr(16 - len(s) % 16) * (16 - len(s) % 16)
unpad = lambda s: s[:-s[-1]]



#发送函数
def send():

    current_timestamp = time.time()
    readable_time = time.ctime(current_timestamp)
    send_data = input()
    send_data = str(readable_time) + ": " + send_data

    print("消息的哈希值为:%s" % Hash(send_data))
    print("哈希值与明文的拼接为: %s" % Hash(send_data)+send_data)
    data,key =  Once_Encryption(
            Hash(send_data)+ "####"+send_data+"####"
        )
    # print(type(data))
    # print(type(key))
    send_data = (r"Plaintext:"+data+"####").encode()+key
    print("拼接加密后的一次秘钥和密文是: %s" % send_data)
    print("----------------------------发送完毕--------------------------")
    udpclient.sendto(send_data,('127.0.0.1',8866))



def Decry_With_A(hash_indicator):
    with open('F:/学习/专业课/信息安全课件/Key_For_Sender/private.pem', 'rb') as key_file:
        private_key = serialization.load_pem_private_key(
            key_file.read(),
            password=None
        )
    print(len(hash_indicator))
    Hash_decrypt = private_key.decrypt(
        hash_indicator,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    print("解密后的一次性秘钥是:%s" % Hash_decrypt)
    return Hash_decrypt


#使用一次性秘钥对密文解密
def aes_AES_Decrypt(ciphertext, key):
    ciphertext = base64.b64decode(ciphertext)
    print("密文经过Base64解密后为:%s " % ciphertext)

    print(len(ciphertext))

    cipher = AES.new(key.encode(), AES.MODE_ECB)

    plaintext = cipher.decrypt(ciphertext)

    return plaintext

#接收函数
def receive():
    data, addr = udpclient.recvfrom(1024)
    # 处理数据的逻辑
    print("收到的密文是 %s" % data)
    print(type(data))

    pattern = b'Plaintext\xef\xbc\x9a(.*)####(.*)'
    match = re.match(pattern, data, re.DOTALL)

    if match:
        plaintext = match.group(1)
        hash_indicator = match.group(2)
        print("分离出的密文是:%s" % plaintext)
        print("分离出的一次性秘钥是:%s " % hash_indicator)
        # 读取私钥 解密一次性秘钥
        Hash_Decrypt = Decry_With_A(hash_indicator)
        # 对密文解密
        print(type(Hash_Decrypt))

        matchup = b'(.*)'
        Match = re.match(matchup, Hash_Decrypt, re.DOTALL)
        print("一次性秘钥转换成字符串为: %s " % Match.group(1).decode())
        hash = Match.group(1).decode()
        if Match:
            plain_message_hash = aes_AES_Decrypt(plaintext, hash)
            print("密文ECB解密后为:%s" % plain_message_hash)

            # 开始分离密文中的Hash值与明文
            value = b'(.*)####(.*)####'
            Match_config = re.match(value, plain_message_hash, re.DOTALL)
            if Match_config:
                message_hash = Match_config.group(1)
                message = Match_config.group(2)
                # 转换成字符串
                value1 = b'(.*)'
                value2 = b'(.*)'
                Hash_Message = re.match(value1, message_hash).group(1).decode()
                Message = re.match(value2, message).group(1).decode()
                print("密文中分离出的Hash值为 :%s " % Hash_Message)
                print("密文中分离出的明文是 %s " % Message)

                if Hash(Message) == Hash_Message:
                    print("明文哈希值为: %s" % Hash(Message))
                    print("明文哈希值与传输的哈希值相同,认证匹配成功")
                    print("----------------------------------------------------------------------")
                else:
                    print("认证匹配失败")
            else:
                print("从密文中分离Hash和明文失败")
        else:
            print("Hash值正则匹配失败")


    else:
        print("分离消息失败")

#产生随机数
def generate_64bit_random():
    bits = ""
    for _ in range(64):
        bits += str(random.randint(0, 10))
    return int(bits, 10)

#将消息转换成Hash函数
def Hash(send_data):
    return  hashlib.sha256(send_data.encode()).hexdigest()



#产生私钥和公钥
def Pub_Pri_Key():
    private_key = rsa.generate_private_key(public_exponent=65537,key_size=2048)
    public_key = private_key.public_key()
    #序列化密钥对
    private_pem = private_key.private_bytes(encoding=serialization.Encoding.PEM,format=serialization.PrivateFormat.PKCS8,encryption_algorithm=serialization.NoEncryption())
    public_pem = public_key.public_bytes(encoding=serialization.Encoding.PEM,format=serialization.PublicFormat.SubjectPublicKeyInfo)
    # 将私钥保存为文件
    with open("F:/学习/专业课/信息安全课件/Key_For_Sender/private.pem", "wb") as file:
        file.write(private_pem)

    # 将公钥保存为文件
    with open("F:/学习/专业课/信息安全课件/Key_For_Sender/public.pem", "wb") as file:
        file.write(public_pem)
    return private_pem.decode(),public_pem.decode()

#一次秘钥和密文一起传递给接收方
def aes_ECB_Encrypt(data, key):  # ECB模式的加密函数,data为明文,key为16字节密钥
    key = key.encode('utf-8')
    # 补位
    data = pad(data)
    data = data.encode('utf-8')
    aes = AES.new(key=key, mode=AES.MODE_ECB)  # 创建加密对象
    # encrypt AES加密  B64encode为base64转二进制编码
    # print(len(data)%16)
    print("ECB加密前的密文是 %s" % data)
    print("ECB加密的密文是:%s" % aes.encrypt(data))
    result = base64.b64encode(aes.encrypt(data))
    print("利用Base64加密后的结果:%s" % result)
    # print("利用一次秘钥加密后的密文是 %s" % result)
    return str(result,'utf-8')  # 以字符串的形式返回

#生成一次性秘钥
def produce_once_key(length = 16):
    letters = string.ascii_letters + string.digits  # stores upper and lower
    # character and digit in ‘letters’ variable
    otp = ''.join(random.choice(letters) for _ in range(length))
    print("发送方生成的一次性秘钥是:%s " % otp)
    return otp



def Encrypt_With_PubB(content):

    # 加载公钥
    with open("F:/学习/专业课/信息安全课件/Key_For_Receiver/public.pem", "rb") as key_file:
        public_key = serialization.load_pem_public_key(
            key_file.read(),
            backend=default_backend()
        )
    # 使用公钥初始化加密对象
    print("进行RSA加密前的一次秘钥为: %s" % content)

    # print(type(content))
    #加密成字节

    #
    # # 使用RSA公钥加密字符串
    ciphertext = public_key.encrypt(
        content.encode(),
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    print("RSA加密后的一次秘钥是 %s " % ciphertext)

    # 计算需要添加的等号数
    # num_padding = 4 - (len(ciphertext) % 4)
    # if num_padding < 4:
    #     ciphertext += "=" * num_padding

    return  ciphertext


# 定义一次加密,使用AES加密
def Once_Encryption(send_data,length=16):
    #生成一次性秘钥
    otp = produce_once_key()

    # 字符串位数不够时的处理
    text = send_data + chr(16 - len(send_data) % 16) * (16 - len(send_data) % 16)
    # 解密时的函数:       text = data + chr(16 - len(data) % 16) * (16 - len(data) % 16)
    # print(len(text)%16)
    Encryt_Once_key = Encrypt_With_PubB(otp)
    return aes_ECB_Encrypt(text,otp),Encryt_Once_key


#接收方的公钥:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxqNI8YcXFC5VaCVHRFkWJ8jqtMMjSs1s6Hj9CSrt2EIIxGqXKJVi60FlF4i04RDAh4xEVxADIAdyS0l5ojEa5w8lUwvzHTvQoviZ7QbU5WkNKYaQTkRj517yhc43vvaAp0yxIAe+B+gGTjFJxLng5AoJSaMCYeewAE5wZGrSUt3GNGEf1parV1IBl5XOnLE79VS27aCi5XchzCchKZXo0voXU6NGgBQuWuO8zk1ZsKSie+p8l9m9TV0cN/9hDKrk10IsEGHsJX81gYso0EeM5cFTVRd1UKklE5eOFFIGYW2fmOxlnAcNI3EFIYqsWOlCqPUO5krmCwZk74r1Qe4qeQIDAQAB






if __name__ == "__main__":
    print("本机的私钥与公钥分别是: ")
    print("%s,%s" % Pub_Pri_Key())
    print("Client is running!"+"\n")

    print("please input message:"+"\n")

    while True:
        thread_send = threading.Thread(target=send, args=())
        thread_recv = threading.Thread(target=receive, args=())
        thread_send.start()
        thread_recv.start()
        thread_send.join()
        thread_recv.join()


    udpclient.close()

        模拟代码,服务器端

#部署在本地的服务器
import hashlib
import random
import socket
import time
import threading
import base64
from Crypto.Cipher import AES
import re
import chardet
import string
from cryptography.hazmat.primitives.asymmetric import rsa,padding
from cryptography.hazmat.primitives import serialization,hashes
from cryptography.hazmat.backends import default_backend
import sys

sys.setrecursionlimit(100000) #例如这里设置为十万




#AES加密时位数不够时填充 接收时去除填充块的方法
pad = lambda s: s + chr(16 - len(s) % 16) * (16 - len(s) % 16)
unpad = lambda s: s[:-s[-1]]



#服务器端代码
udpserver = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
udpserver.bind(('127.0.0.1',8866))

#将消息转换成Hash函数
def Hash_Encrypt(send_data):
    return  hashlib.sha256(send_data.encode()).hexdigest()


def Decry_With_B(hash_indicator):
    with open('F:/学习/专业课/信息安全课件/Key_For_Receiver/private.pem', 'rb') as key_file:
        private_key = serialization.load_pem_private_key(
            key_file.read(),
            password=None
        )
    print(len(hash_indicator))
    Hash_decrypt = private_key.decrypt(
        hash_indicator,
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    print("解密后的一次性秘钥是:%s" % Hash_decrypt)
    return Hash_decrypt


#使用对方的公钥加密一次性秘钥

def Encrypt_With_PubA(content):

    # 加载公钥
    with open("F:/学习/专业课/信息安全课件/Key_For_Sender/public.pem", "rb") as key_file:
        public_key = serialization.load_pem_public_key(
            key_file.read(),
            backend=default_backend()
        )
    # 使用公钥初始化加密对象
    print("进行RSA加密前的一次秘钥为: %s" % content)

    # # 使用RSA公钥加密字符串
    ciphertext = public_key.encrypt(
        content.encode(),
        padding.OAEP(
            mgf=padding.MGF1(algorithm=hashes.SHA256()),
            algorithm=hashes.SHA256(),
            label=None
        )
    )
    print("RSA加密后的一次秘钥是 %s " % ciphertext)
    return  ciphertext

#使用ECB加密
def aes_ECB_Encrypt(data,key):   # ECB模式的加密函数,data为明文,key为16字节密钥
    key = key.encode('utf-8')
    # 补位
    data = pad(data)
    data = data.encode('utf-8')
    aes = AES.new(key=key, mode=AES.MODE_ECB)  # 创建加密对象
    # encrypt AES加密  B64encode为base64转二进制编码
    # print(len(data)%16)
    print("ECB加密前的密文是 %s" % data)
    print("ECB加密的密文是:%s" % aes.encrypt(data))
    result = base64.b64encode(aes.encrypt(data))
    print("利用Base64加密后的结果:%s" % result)
    # print("利用一次秘钥加密后的密文是 %s" % result)
    return str(result,'utf-8')  # 以字符串的形式返回


#使用一次性秘钥对密文解密
def aes_AES_Decrypt(ciphertext, key):
    ciphertext = base64.b64decode(ciphertext)
    print("密文经过Base64解密后为:%s " % ciphertext)

    # print(len(ciphertext))

    cipher = AES.new(key.encode(), AES.MODE_ECB)

    plaintext = cipher.decrypt(ciphertext)

    return plaintext


#产生随机数
def generate_64bit_random():
    bits = ""
    for _ in range(64):
        bits += str(random.randint(0, 10))
    return int(bits, 10)


def receive():
    data, addr = udpserver.recvfrom(1024)
   #处理数据的逻辑
    print("收到的密文是 %s" % data)
    print(type(data))

    pattern = b'Plaintext\xef\xbc\x9a(.*)####(.*)'
    match = re.match(pattern, data,re.DOTALL)

    if match:
        plaintext = match.group(1)
        hash_indicator = match.group(2)
        print("分离出的密文是:%s" % plaintext)
        print("分离出的一次性秘钥是:%s "% hash_indicator)
        #读取私钥 解密一次性秘钥
        Hash_Decrypt = Decry_With_B(hash_indicator)
        #对密文解密
        print(type(Hash_Decrypt))

        matchup = b'(.*)'
        Hash = re.match(matchup, Hash_Decrypt, re.DOTALL)
        print("一次性秘钥转换成字符串为: %s "%  Hash.group(1).decode())
        hash = Hash.group(1).decode()
        if Hash:
            plain_message_hash = aes_AES_Decrypt(plaintext, hash)
            print("密文ECB解密后为:%s" % plain_message_hash)


            #开始分离密文中的Hash值与明文
            value = b'(.*)####(.*)####'
            Match_config = re.match(value,plain_message_hash,re.DOTALL)
            if Match_config:
                message_hash = Match_config.group(1)
                message = Match_config.group(2)
                #转换成字符串
                value1 = b'(.*)'
                value2 = b'(.*)'
                Hash_Message = re.match(value1,message_hash).group(1).decode()
                Message = re.match(value2,message).group(1).decode()
                print("密文中分离出的Hash值为 :%s " % Hash_Message)
                print("密文中分离出的明文是 %s " % Message)

                if Hash_Encrypt(Message) == Hash_Message:
                    print("明文哈希值为: %s" % Hash_Encrypt(Message))
                    print("明文哈希值与传输的哈希值相同,认证匹配成功")
                    print("----------------------------------------------------------------------")
                else:
                    print("认证匹配失败")
            else:
                print("从密文中分离Hash和明文失败")
        else:
            print("Hash值正则匹配失败")


    else:
        print("分离消息失败")










def send():
    current_timestamp = time.time()
    readable_time = time.ctime(current_timestamp)
    send_data = input()
    send_data = str(readable_time) + ": " + send_data

    print("消息的哈希值为:%s" % Hash_Encrypt(send_data))
    print("哈希值与明文的拼接为: %s" % Hash_Encrypt(send_data) + send_data)
    data, key = Once_Encryption(
        Hash_Encrypt(send_data) + "####" + send_data + "####"
    )
    # print(type(data))
    # print(type(key))
    send_data = (r"Plaintext:" + data + "####").encode() + key
    print("拼接加密后的一次秘钥和密文是: %s" % send_data)
    print("----------------------------发送完毕--------------------------")
    udpserver.sendto(send_data,('127.0.0.1',8888))


#产生私钥和公钥
def Pub_Pri_Key():
    private_key = rsa.generate_private_key(public_exponent=65537,key_size=2048)
    public_key = private_key.public_key()
    #序列化密钥对
    private_pem = private_key.private_bytes(encoding=serialization.Encoding.PEM,format=serialization.PrivateFormat.PKCS8,encryption_algorithm=serialization.NoEncryption())
    public_pem = public_key.public_bytes(encoding=serialization.Encoding.PEM,format=serialization.PublicFormat.SubjectPublicKeyInfo)
    # 将私钥保存为文件
    with open("F:/学习/专业课/信息安全课件/Key_For_Receiver/private.pem", "wb") as file:
        file.write(private_pem)

    # 将公钥保存为文件
    with open("F:/学习/专业课/信息安全课件/Key_For_Receiver/public.pem", "wb") as file:
        file.write(public_pem)

    return private_pem.decode(),public_pem.decode()



#生成一次性秘钥
def produce_once_key(length = 16):
    letters = string.ascii_letters + string.digits  # stores upper and lower
    # character and digit in ‘letters’ variable
    otp = ''.join(random.choice(letters) for _ in range(length))
    print("发送方生成的一次性秘钥是:%s " % otp)
    return otp

#定义一次加密,使用AES加密
def Once_Encryption(send_data):
    #生成一次性秘钥
    otp = produce_once_key()

    # 字符串位数不够时的处理
    text = send_data + chr(16 - len(send_data) % 16) * (16 - len(send_data) % 16)
    # 解密时的函数:       text = data + chr(16 - len(data) % 16) * (16 - len(data) % 16)
    # print(len(text)%16)
    Encryt_Once_key = Encrypt_With_PubA(otp)
    return aes_ECB_Encrypt(text,otp),Encryt_Once_key



if __name__ == '__main__':
    print("服务器端的公钥与私钥分别是:")
    print("%s,%s" % Pub_Pri_Key())
    print("Server is running!")
    thread_send = threading.Thread(target=send,args=())
    thread_recv = threading.Thread(target=receive,args=())
    print("please input massage:\n")

    while True:
        thread_send = threading.Thread(target=send, args=())
        thread_recv = threading.Thread(target=receive, args=())
        thread_send.start()
        thread_recv.start()
        thread_send.join()
        thread_recv.join()


你可能感兴趣的:(数据库)