zoukankan      html  css  js  c++  java
  • 20192426 实验三《Python程序设计》实验报告

    课程:《Python程序设计》
    班级: 1924
    姓名: 陈瀚文
    学号: 20192426
    实验教师:王志强
    实验日期:2020年5月16日
    必修/选修: 公选课

    1.实验内容

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

    2. 实验过程及结果

    实验过程:

    1. 首先,我构思了整体代码的布局:先由客户端使用base64加密密钥并传输给服务端,服务端接收密钥后解密得到密钥,之后客户端读取文件并将文件内容使用密钥进行DES加密后发送给服务端,服务端接收文件后使用密钥解密并保存到文件中。

    2. 接着,我根据所需要实现的功能导入了以下模块:

       import socket
       import os
       from Cryptodome.Cipher import DES
       import base64
      
    3. 之后是代码部分,服务端的代码如下(码云直达):

      # -*- encoding: utf-8 -*-
      '''
      文件:    Experiment3S.py
      时间:    2020/05/16 13:37:02
      作者:    20192426 陈瀚文
      '''
      
      import socket
      import os
      from Cryptodome.Cipher import DES
      import base64
      
      os.chdir("D:\网空专业\大一下\Python程序设计\Learnpython\Experiment")
      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      s.bind(('127.0.0.1', 8080))  # 绑定地址到套接字
      s.listen()  # 开启TCP监听
      conn, address = s.accept()  # 等待连接到来
      print("来自", address, "的信息:", conn.recv(1024).decode())    # 接收客户端的信息
      conn.sendall("请发送密钥!".encode())    # 向客户端请求密钥
      key = base64.b64decode(conn.recv(1024))  # 接收密钥并解密
      conn.sendall("已收到密钥!".encode())    # 反馈信息
      print("密钥为:", key)  # 输出密钥
      des = DES.new(key, DES.MODE_ECB)    # 创建一个DES实例
      name = conn.recv(1024)  # 接收文件名
      print("来自", address, "的文件:", name.decode())  # 打印接收到的文件名
      data = conn.recv(1024)  # 接收文件内容
      
      # 将接收到的内容保存到文件Ex3receive.txt中
      f = open("Ex3receive.txt", "w", encoding="utf8")
      f.write(des.decrypt(data).decode().rstrip(
          ' '))
      f.close()
      
      print("来自", address, "的信息:", des.decrypt(data).decode().rstrip(
          ' '), "已保存为receive.txt")  # 打印接收到的信息
      conn.sendall("服务器已经收到了数据内容!".encode())  # 与客户端进行交互
      data = conn.recv(1024)  # 接收反馈
      s.close()  # 关闭套接字
      
    4. 根据已有的服务端的代码,我完成了客户端代码的编写,首先,导入和服务端相同的模块。

      import socket
      import os
      from Cryptodome.Cipher import DES
      import base64
      
    5. 接着,通过参考资料我定义了一个函数pad(),用于将加密文本的大小补足为8的倍数。

      def pad(text):
          """
          参考:https://blog.csdn.net/yangxiaodong88/article/details/80801278
          ### 加密函数,如果text不是8的倍数【加密文本text必须为8的倍数!】,那就补足为8的倍数
          :param text:
          :return:
          """
          while len(text) % 8 != 0:
              text += ' '
          return text
      
    6. 最后完成了客户端函数的主体部分:

      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      s.connect(('127.0.0.1', 8080))  # 初始化TCP服务器连接
      
      key = "qwerasdf".encode()   # 将密钥编码为二进制格式
      des = DES.new(key, DES.MODE_ECB)    # 创建DES实例
      
      str1 = input("请输入要传输的文件名:")  # 输入文件名
      s.sendall("请接收密钥!".encode())  # 提示服务端接收密钥
      print("来自 ('127.0.0.1', 8080) 的信息:", s.recv(1024).decode())   # 接收服务端反馈
      s.sendall(base64.b64encode(key))    # 发送加密的密钥
      print("来自 ('127.0.0.1', 8080) 的信息:", s.recv(1024).decode())   # 接收服务端反馈
      
      s.sendall(str1.encode())  # 发送文件名
      os.chdir("D:\网空专业\大一下\Python程序设计\Learnpython\Experiment")
      file = open('{}'.format(str1), 'r', encoding="utf8")  # 打开目标文件
      text = file.read()  # 读取文件信息
      # 参考了https://blog.csdn.net/yangxiaodong88/article/details/80801278
      padded_text = pad(text)
      encrypted_text = des.encrypt(padded_text.encode('utf-8'))  # 加密
      s.sendall(encrypted_text)  # 发送文件信息
      file.close()
      data = s.recv(1024)  # 接收反馈信息
      print("来自 ('127.0.0.1', 8080) 的信息:", data.decode())  # 打印接收到的信息
      s.sendall("收到".encode())  # 回复服务器
      s.close()  # 关闭套接字
      
    7. 客户端的代码如下(码云直达):

      # -*- encoding: utf-8 -*-
      '''
      文件:    Experiment3C.py
      时间:    2020/05/16 13:46:56
      作者:    20192426 陈瀚文
      '''
      
      import socket
      import os
      from Cryptodome.Cipher import DES
      import base64
      
      
      def pad(text):
          """
          参考:https://blog.csdn.net/yangxiaodong88/article/details/80801278
          ### 加密函数,如果text不是8的倍数【加密文本text必须为8的倍数!】,那就补足为8的倍数
          :param text:
          :return:
          """
          while len(text) % 8 != 0:
              text += ' '
          return text
      
      
      s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      s.connect(('127.0.0.1', 8080))  # 初始化TCP服务器连接
      
      key = "qwerasdf".encode()   # 将密钥编码为二进制格式
      des = DES.new(key, DES.MODE_ECB)    # 创建DES实例
      
      str1 = input("请输入要传输的文件名:")  # 输入文件名
      s.sendall("请接收密钥!".encode())  # 提示服务端接收密钥
      print("来自 ('127.0.0.1', 8080) 的信息:", s.recv(1024).decode())   # 接收服务端反馈
      s.sendall(base64.b64encode(key))    # 发送加密的密钥
      print("来自 ('127.0.0.1', 8080) 的信息:", s.recv(1024).decode())   # 接收服务端反馈
      
      s.sendall(str1.encode())  # 发送文件名
      os.chdir("D:\网空专业\大一下\Python程序设计\Learnpython\Experiment")
      file = open('{}'.format(str1), 'r', encoding="utf8")  # 打开目标文件
      text = file.read()  # 读取文件信息
      # 参考了https://blog.csdn.net/yangxiaodong88/article/details/80801278
      padded_text = pad(text)
      encrypted_text = des.encrypt(padded_text.encode('utf-8'))  # 加密
      s.sendall(encrypted_text)  # 发送文件信息
      file.close()
      data = s.recv(1024)  # 接收反馈信息
      print("来自 ('127.0.0.1', 8080) 的信息:", data.decode())  # 打印接收到的信息
      s.sendall("收到".encode())  # 回复服务器
      s.close()  # 关闭套接字
      

    实验结果:

    服务端:

    客户端:

    后续:

    在这之后,我使用了我的阿里云服务器进行了测试,以该服务器作为服务端,修改了部分代码,其中,将服务端的绑定地址修改为了172.17.232.247(服务器内网IP),将客户端连接地址修改为了39.96.51.81(服务器公网IP),完成了远程连接,结果如下:

    服务端(码云直达):

    客户端(码云直达):

    3. 实验过程中遇到的问题和解决过程

    • 问题1:在进行加密解密的时候,出现了'***' has type str, but expected one of: bytes
    • 问题1解决方案:通过encode函数将对象转换成二进制类型,报错消失。
    • 问题2:在远程服务器上运行代码时,错将socket绑定至公网IP,导致无法连接端口
    • 问题2解决方案:查询到了服务器的内网IP,将服务端的socket绑定至内网IP上,正确运行。

    其他(感悟、思考等)

    • 在传输使用对称加密算法加密的文件时密钥的传输也应当注意安全,可以利用base64等算法加密密钥再将密钥传输给服务端。
    • 通过上课以及本次实验,我对socket网络编程有了进一步地认识,同时对于网络传输的大概过程也有了一定的了解。
    • python的种类繁多的第三方库使得python这种语言使用起来非常舒服,使得一些较为复杂的过程可以轻松实现

    参考资料

  • 相关阅读:
    7-20 (样卷)统计单词的个数 (40 分)
    7-21 删除字符 (30 分)
    7-19 计算有n个字符串中最长的字符串长度 (40 分)
    7-16 列表数字元素加权和(1) (40 分)
    7-17 列表元素个数的加权和(1) (40 分)
    7-15 求出歌手的得分 (40 分)
    7-10 jmu-python-异常-学生成绩处理基本版 (15 分)
    7-11 jmu-python-分段函数&数学函数 (15 分)
    7-12 产生每位数字相同的n位数 (30 分)
    7-9 jmu-python-异常-学生成绩处理专业版 (25 分)
  • 原文地址:https://www.cnblogs.com/chw123/p/12901323.html
Copyright © 2011-2022 走看看