码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2020-07-30 22:17:38      阅读:88      评论:0      收藏:0      [点我收藏+]

标签:返回结果   固定   bind   mod   abs   一段   recv   ror   struct   

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:\Python\Python_Project\day30\01.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:\Python\Python_Project\day30\01今日内容大纲以及内容回顾.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‘2\xf9\xb9\x02\xeb\xfes\x06T\x8b\xd9\xc1\xc0\xc3L\x0f‘

四、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)

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

标签:返回结果   固定   bind   mod   abs   一段   recv   ror   struct   

原文地址:https://www.cnblogs.com/raygor/p/13406054.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!