20202107 《Python程序設計》實驗三報告

課程:《Python程序設計》
班級: 2021
姓名: 張權城
學號:20202107
實驗教師:王志強
實驗日期:2022年4月21日
必修/選修: 公選課

1.實驗內容

創建服務端和客戶端,服務端在特定端口監聽多個客戶請求。客戶端和服務端通過Socket套接字(TCP/UDP)進行通信。
要求:
(1)創建服務端和客戶端,選擇一個通信端口,用Python語言編程實現通信演示程序;
(2)要求包含文件的基本操作,例如打開和讀寫操作。
(3)要求發送方從文件讀取內容,加密后并傳輸;接收方收到密文并解密,保存在文件中。
(4)程序代碼托管到碼云。

2. 實驗過程及結果

(1)設計思路

該實驗目標是制作一個基于socket的通訊器,根據之前課上學習的內容及課后作業,本次實驗不難完成。
加密上選擇的是基于pyDes的CBC模式DES加密,實現了客服端與服務器的雙向加密通信。基于Python標準庫tkinter,實現了可視化選擇目標文件的功能。但由于沒有具體實現tkinter窗體(極其不標準的使用方法),導致使用該功能后會有一個無內容的tkinter窗體殘留,雖然不影響總體使用,但對程序的完成性和一致性有所破壞。

(2)主要代碼介紹

部分代碼有參考。
報告中只貼出了部分代碼,全部代碼已上傳碼云:服務器部分客戶端部分DES加解密部分

  • 加解密部分:
    基于pyDes庫實現DES加解密功能。
from pyDes import des, CBC, PAD_PKCS5
import binascii
key_ = '12345675'
def des_encrypt(s):
    """
    DES 加密
    :param s: 原始字符串
    :return: 加密后字符串,16進制
    """
    secret_key = key_
    iv = secret_key
    k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
    en = k.encrypt(s, padmode=PAD_PKCS5)
    return binascii.b2a_hex(en)
def des_descrypt(s):
    """
    DES 解密
    :param s: 加密后的字符串,16進制
    :return:  解密后的字符串
    """
    secret_key = key_
    iv = secret_key
    k = des(secret_key, CBC, iv, pad=None, padmode=PAD_PKCS5)
    de = k.decrypt(binascii.a2b_hex(s), padmode=PAD_PKCS5)
    return de
  • 客戶端部分:
    循環發送字符串給服務器。取'close_'作為關閉連接的保留字。
import socket
from mydes import des_descrypt, des_encrypt
from tkinter.filedialog import askopenfilename
if __name__ == '__main__':
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(('127.0.0.1', 8001))
    print('連接服務器成功')
    while True:
        ch = input('1.發送字符串 2.發送文件 3.退出\n請選擇想要使用的功能:')
        if ch == '1':
            str_ = input('請輸入要傳輸的內容:')
        elif ch == '2':
            filename = askopenfilename()
            with open(filename, 'r', encoding='utf-8') as f:
                str_ = f.read()
        elif ch == '3':
            str_ = 'close_'
            str_ = des_encrypt(str_)
            s.sendall(str_)
            break
        else:
            print('無該選項,請重新輸入')
        str_ = des_encrypt(str_)
        # print(type(str_))
        s.sendall(str_)
        data = s.recv(1024)
        data = des_descrypt(data)
        print(data.decode())
    s.close()
    print('連接已關閉')
  • 服務器部分:
    循環接收客戶端發送的數據,并寫入文件中。取'close_'作為關閉連接的保留字。
import socket
from mydes import des_descrypt, des_encrypt


if __name__ == '__main__':
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind(('127.0.0.1', 8001))
    print('服務器已創建,正在監聽中...')
    s.listen()
    conn, address = s.accept()
    while True:
        data = conn.recv(1024)
        data = des_descrypt(data)
        # print(data, type(data))
        if data == b'close_':
            break
        else:
            with open('received', 'wb') as f:
                f.write(data)
            str_ = '服務器已接收:'+str(data)
            str_ = des_encrypt(str_.encode())
            conn.sendall(str_)
            print('接收數據:', data.decode(), '\n已寫入received.txt文件中')
    s.close()
    print('服務器關閉')

(4)程序結果

客戶端:

  • 發送字符串:
  • 發送文件
  • 結束連接

    服務器:

3. 實驗過程中遇到的問題和解決過程

暫無。

其他(感悟、思考等)

socket編程是我以前沒有涉及過的領域,在python課上能夠學到很多實用的知識,拓寬我的視野讓我受益良多。

 

碼云鏈接:https://gitee.com/zhang-quancheng-2107/zqc.python.test.git