python 网络编程-04 文件的传输

  1. 文件传输需要要hashlib 来验证文件的完整性
  2. 需要判断文件是否传输完成

文件完整性判断

import hashlib
md5 = hashlib.sha3_256()
md5.update(msg)

update 为追加完整性判断

md5.update(b'hello world')
与
md5.update(b'hello ')
md5.update(b'world')

hash 值完全相同

实现

proto.py

import struct
import hashlib


def sender(conn, msg: bytes):

    pack_head = struct.pack('i', len(msg))
    conn.send(pack_head)
    conn.send(msg)


def receiver(conn) -> str:
    length = struct.unpack('i', conn.recv(4))[0]
    msg = ''
    while True:
        if length < 1024:
            recv_msg = conn.recv(length)
            msg += recv_msg.decode('utf-8')
            break
        else:
            recv_msg = conn.recv(1024)
            length -= 1024
            msg = recv_msg.decode('utf-8')

    return msg


class HashCheck:
    def __init__(self):
        self.md5 = hashlib.sha3_256()

    def hash_md5(self, msg: bytes):
        self.md5.update(msg)

server.py

import socket, traceback
from 文件传送与文件校验 import proto


def recv_file(c, filename):
    md5obj = proto.HashCheck()
    with open(filename, 'w') as f:
        """
        1. 获取文件大小
        2. 循环获取文件行
        3. 追加验证文件完整性,并将文件行内容写入文件
        4. 文件读完后 获取文件的MD5
        5. 将获取的MD5与 计算的MD5 进行比较。
        """

        size = proto.receiver(c)
        file_size = int(size)
        while True:
            try:
                line = proto.receiver(c)
                md5obj.hash_md5(line.encode('utf-8'))
                f.write(line)
                file_size -= len(line)

                #  文件接收完成
                if file_size == 0:
                    break

            except Exception as e:
                print('连接异常')
                c.close()
                print(traceback.print_exc())
                break
        hash_md5 = proto.receiver(c)
        if hash_md5 == md5obj.md5.hexdigest():
            print('file receive success!')
        else:
            print('file receive failed!')


if __name__ == '__main__':
    s = socket.socket()
    s.bind(('127.0.0.1', 8000))
    s.listen()
    while True:
        print('等待连接')
        conn, addr = s.accept()

        recv_file(conn, 'server1.txt')

client.py

import socket
import os
from 文件传送与文件校验 import proto


def send_file(filename):
    s = socket.socket()
    s.connect(('127.0.0.1', 8000))
    # 获取文件大小
    size = os.path.getsize(filename)
    # 发送文件大小
    proto.sender(s, str(size).encode('utf-8'))

    with open(filename, 'rb') as f:
        # 创建md5 的验证对象
        md5obj = proto.HashCheck()
        for line in f:
            # 追加MD5 验证
            md5obj.hash_md5(line)
            # 发送文件行
            proto.sender(s, line)
    proto.sender(s, md5obj.md5.hexdigest().encode('utf-8'))
    s.close()


if __name__ == '__main__':
    send_file('client.txt')

posted @ 2020-03-03 15:54  hurz  阅读(634)  评论(0编辑  收藏  举报