zoukankan      html  css  js  c++  java
  • Python基础学习(29)基于TCP协议的文件传输 验证客户端合法性 socketserver模块处理并发客户端请求

    Python基础学习(29)基于TCP协议的文件传输 验证客户端合法性 socketserver 模块处理并发客户端请求

    一、今日内容

    • 基于 TCP 协议的文件传输
    • 验证客户端合法性
    • socketserver 模块处理并发客户端请求

    二、基于 TCP 协议的文件传输

    1. 基本功能实现

      # server.py
      
      import socket
      import json
      # 接收
      sk = socket.socket()
      sk.bind(('127.0.0.1', 9000))
      
      sk.listen()
      
      conn, addr = sk.accept()
      msg = conn.recv(1024).decode('utf-8')
      msg = json.loads(msg)
      with open(msg['filename'] + '.bak', 'wb') as f:
          content = conn.recv(msg['filesize'])
          f.write(content)
      conn.close()
      
      sk.close()
      
      # client.py
      
      import socket
      import os
      import json
      # 发送
      sk = socket.socket()
      sk.connect(('127.0.0.1', 9000))
      
      ABS_PATH = r'D:PythonPython_Projectday301.TCP协议完成文件上传.py'
      file_name = os.path.basename(ABS_PATH)
      filesize = os.path.getsize(ABS_PATH)
      dic = {'filename': file_name, 'filesize': filesize}
      str_dic = json.dumps(dic)
      sk.send(str_dic.encode('utf-8'))
      
      with open(ABS_PATH, mode='rb') as f:
          content = f.read()
          sk.send(content)
      
      sk.close()
      
    2. 将大文件分成若干块传输

      # server.py
      
      import socket
      import json
      import struct
      # 接收
      sk = socket.socket()
      sk.bind(('127.0.0.1', 9000))
      
      sk.listen()
      
      conn, addr = sk.accept()
      b_len = conn.recv(4)
      msg_len = struct.unpack('i', msg_len)[0]
      msg = conn.recv(msg_len).decode('utf-8')
      msg = json.loads(msg)
      with open(msg['filename'] + '.bak', 'wb') as f:
          while msg['filesize'] > 0:
              content = conn.recv(1024)
              # 不能写作1024,因为发送过程中1024会被解包,在接收的时候会分开发送,每次接收不能保证1024
              # 所以要写作len(content)
              msg['filesize'] -= len(content)
              f.write(content)
      conn.close()
      
      sk.close()
      
      import socket
      import os
      import json
      import struct
      # 发送
      sk = socket.socket()
      sk.connect(('127.0.0.1', 9000))
      
      ABS_PATH = r'D:PythonPython_Projectday301今日内容大纲以及内容回顾.mp4'
      file_name = os.path.basename(ABS_PATH)
      filesize = os.path.getsize(ABS_PATH)
      dic = {'filename': file_name, 'filesize': filesize}
      str_dic = json.dumps(dic)
      b_dic = str_dic.encode('utf-8')
      b_length = struct.pack('i', len(b_dic))
      sk.send(b_length)
      sk.send(b_dic)
      
      with open(ABS_PATH, mode='rb') as f:
          while filesize > 0:
              content = f.read(1024)
              filesize -= len(content)
              sk.send(content)
      
      sk.close()
      

    三、验证客户端合法性

    • 为什么要验证客户端合法性:因为服务端提供服务的过程中,有可能遭遇攻击,所以必须要验证客户端的合法身份,才能够与其建立通信;
    • 如何实现验证客户端合法性:在合法的客户端和服务端之间约定一个"密钥",服务端在与未知客户端之间建立通信时先随机生成一段定长字符串发送给客户端,服务以密钥作为 salt 加密后返回给服务端,服务端进行相同操作后与返回结果对比,如果相同则为合法客户端。
    # server.py
    
    import os
    import hashlib
    import socket
    
    KEY = '19960624'
    Auth_sta = []
    
    sk = socket.socket()
    sk.bind(('127.0.0.1', 9000))
    sk.listen()
    
    conn, addr = sk.accept()
    auth_b = os.urandom(32)
    conn.send(auth_b)
    sha = hashlib.sha1(KEY.encode('utf-8'))
    sha.update(auth_b)
    res = conn.recv(1024).decode('utf-8')
    if res == sha.hexdigest():
        Auth_sta.append(addr)
        print('1')
    
    # client.py
    
    import hashlib
    import socket
    
    KEY = '19960624'
    
    sk = socket.socket()
    sk.connect(('127.0.0.1', 9000))
    
    auth_b = sk.recv(32)
    sha = hashlib.sha1(KEY.encode('utf-8'))
    sha.update(auth_b)
    sk.send(sha.hexdigest().encode('utf-8'))
    
    # hmac 模块  用来替代hashlib模块,更简单验证网络合法性
    import os
    import hmac
    
    h = hmac.new(b'alex_sb', os.urandom(32))
    ret1 = h.digest()
    print(ret1)  # b'2xf9xb9x02xebxfesx06Tx8bxd9xc1xc0xc3Lx0f'
    

    四、socketserver 模块处理并发客户端请求

    socketserver 模块是基于 socket 模块完成的,封装度较高,效率比较固定,可以用来处理 TCP 协议下客户端的并发请求:

    # server.py
    
    import socketserver
    import time
    
    class Myserver(socketserver.BaseRequestHandler):
        def handle(self):
            conn = self.request  # self.request 就是 conn
            while True:
                try:
                    content = conn.recv(1024).decode('utf-8')
                    conn.send(content.upper().encode('utf-8'))
                    time.sleep(0.5)
                except ConnectionResetError:
                    break
                    
    server = socketserver.ThreadingTCPServer(('127.0.0.1', 9000), Myserver)
    server.serve_forever()
    
    import socket
    
    sk = socket.socket()
    sk.connect(('127.0.0.1', 9000))
    
    while True:
        sk.send(b'hello')
        content = sk.recv(1024).decode('utf-8')
        print(content)
    
  • 相关阅读:
    全站防止SQL注入类
    asp.net 技术网站
    Tekla API 常见问题摘录整理
    C#退出程序结束线程
    C#MetroModernUI库应用实例 WinForm窗体UI的美化
    获取项目物理根目录绝对路径
    计算两个时间月数的差
    centos7安装wps软件
    10 安全运维管理 10.11备份与恢复管理
    10 安全运维管理 10.14外包运维管理
  • 原文地址:https://www.cnblogs.com/raygor/p/13406054.html
Copyright © 2011-2022 走看看