实验三 Socket编程技术

 20191130李月 《Python程序设计》实验三报告

课程:《Python程序设计》
班级: 1911
姓名: 李月
学号:20191130
实验教师:王志强
实验日期:2020年5月31日
必修/选修: 公选课

(一)实验内容

创建服务端和客户端,服务端在特定端口监听多个客户请求。客户端和服务端通过Socket套接字(TCP/UDP)进行通信。

(1)创建服务端和客户端,选择一个通信端口,用Python语言编程实现通信演示程序;

(2)要求包含文件的基本操作,例如打开和读写操作。

(3)要求发送方从文件读取内容,加密后并传输;接收方收到密文并解密,保存在文件中。

(二)实验过程及结果

1)监听多个客户端

为了多个客户端多线并行从而采取了线程处理的方式,将监听放入主线程,将处理放入子线程。

SerSock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
SerSock.bind(('127.0.0.1',8001))
SerSock.listen(5)
socks = []  # 存放每个客户端的socket

t = threading.Thread(target=handle)
if __name__ == '__main__':
    t.start()
    print(r'我在%s线程中' % threading.current_thread().name)
    print('waiting for connecting ...')
    while True:
        CliSock,addr = SerSock.accept()
        print('connected from:',addr)
        socks.append(CliSock)

2)客户端连接服务器

CliSock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
serve_ip = input("Please enter the server IP:")
serve_port = int(input("Please enter the corresponding Port:"))  # 端口要是int类型,所有要转换
CliSock.connect((serve_ip, serve_port))  # 连接服务器,建立连接,参数是元组形式

3)通讯循环

为了使通讯可以不断进行,并在需要的时候停止,进行了如下设置。

while True:
    send_data = input("Enter your message:")
    CliSock.send(send_data.encode('utf-8'))
    time.sleep(1)
    if send_data == 'quit':
        print('\ncommunication ended.')
        break
    elif send_data == 'encrypt file':
        filename = input("Please enter the file name:")
        print("If the file is large, the run time will be a little long, please be patient.")
        af_filename = 'Client encrypted.txt'
        time.sleep(1)
        send_out(filename)
        take_in(af_filename)
        decrypt(af_filename)
        print('')
    re = CliSock.recv(1024)
    print("Server is sending:",re.decode('utf-8'))

4)文件发送与接收

为了提高将二者都变为函数,因为传输前后顺序不同,相关的代码也会有所不同。

客户端相关代码

在本实验中的传输文件代码只能传输本目录下的相关文件。

传输代码
def send_out(filename):
    with open(filename, 'rb') as file:
        for i in file:
            CliSock.send(i)
            data = CliSock.recv(1024)
            if data != b'success':
                break
    time.sleep(1)
    CliSock.send('quit'.encode())
    print("... File sent successfully ...")
接收代码
def take_in(af_filename):
    while True:
        with open(af_filename, 'ab') as file:
            data = CliSock.recv(1024)
            if data == b'quit':
                break
            file.write(data)
        time.sleep(1)
        CliSock.sendall('success'.encode())
    print("... File reception completed ...")

服务端相关代码

传输代码
def send_out(filename,s):
    with open(filename, 'rb') as file:
        i = file.read()
        s.send(i)
    time.sleep(1)
    s.send('quit'.encode())
    print("... File sent successfully ...")
接收代码
def take_in(filename,s):
    while True:
        with open(filename, 'ab') as file:
            data = s.recv(1024)
            if data == b'quit':
                break
            file.write(data)
        time.sleep(1)
        s.sendall('success'.encode())
    print("... File reception completed ...")

5)文件的加密以及解密

 

加密代码

def encrypt(filename,af_filename):#加密方法
    key = input("Please set a key:")
    text = open(filename,'rb').read()
    open(filename,'rb').close()
    text = str(text)
    aes = AES.new(add_to_16(key), AES.MODE_ECB)
    encrypt_aes = aes.encrypt(add_to_16(text))
    encrypted_text = str(base64.encodebytes(encrypt_aes), encoding='utf-8')
    logbat = open(af_filename, 'w')
    logbat.write(encrypted_text)
    logbat.close()
    print('... File encrypted successfully ...')

解密代码

def decrypt(af_filename):
    key = input('Please enter the corresponding key:')
    text = str(open(af_filename, 'r').read())  # 密文文件
    open(af_filename, 'r').close()
    aes = AES.new(add_to_16(key), AES.MODE_ECB)  # 初始化加密器
    base64_decrypted = base64.decodebytes(text.encode(encoding='utf-8'))  # 优先逆向解密base64成bytes
    decrypted_text = str(aes.decrypt(base64_decrypted), errors='ignore').replace('\0', '')  # 执行解密
    decrypted_text2 = eval(decrypted_text)
    decrypted_text3 = decrypted_text2.decode('utf-8')
    print("Successfully decrypted, the contents of the file are:")
    print(decrypted_text3)

补足key位数的相关函数代码

在内部实现上,AES只是提供一个接收固定长度密钥和16字节大小的分组,然后生成另外一个不同的16字节大小的分组的数学函数。

def add_to_16(value):# str不是16的倍数那就补足为16的倍数
    while len(value) % 16 != 0:
        value += '\0'
    return str.encode(value)  # 返回bytes

(三)思考感悟

1、一个程序的产生要经历不断地修改。

2、在开始编写程序之前需要把基础知识掌握牢固。

3、编写程序的时候可以采用自顶向下、逐步求精。

4、编写程序需要耐心、细心。

posted @ 2021-05-31 20:19  LYhi  阅读(89)  评论(0编辑  收藏  举报