首页 > 其他 > 详细

第八章 socket网络编程(10):文件传输功能的实现

时间:2019-08-04 20:19:50      阅读:159      评论:0      收藏:0      [点我收藏+]

文件传输功能(下载)

这个可以用上一篇的最终版的远程执行命令代码稍作修改就可以实现。 原理是一样的

下面代码借用之前的ssh代码部分:

从服务器下载文件:
server.py

import socket
import struct
import json
import os.path

# 定义一个共享用文件夹的路径,注意:这部分一般应该写在配置文件中
SHARE_DIR = r'C:\temp'

server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('127.0.0.1', 8080))
server.listen(3)

while True:
    conn, addr = server.accept()  # 等待连接,连接成功时实例化conn对象用来接下来的通信
    while True:
        try:
            # 收命令
            res = conn.recv(1024)  # 接收客户端命令(bytes类型),格式get a.txt
            if not res: break  # 异常处理:防止客户端强制断开连接,导致linux系统死循环
            # 解析命令,提取相应命令参数
            cmds = res.decode('utf-8').split()  # 解码后用空格分割
            filename = cmds[1]

            # 第一步:生成数据的报头信息数据(非固定长度)
            header_dic = {
                'filename': filename,
                'md5': 'xxxx',
                'total_size': os.path.getsize(os.path.join(SHARE_DIR, filename))
            }

            # 将报头encode(网络传输准备)
            header_json = json.dumps(header_dic)
            header_bytes = header_json.encode('utf-8')

            # 第二部:发送报头长度
            conn.send(struct.pack('i', len(header_bytes)))

            # 第三部:再发报头
            conn.send(header_bytes)

            # 第四部:最后发真实数据
            # 以read的模式读取文件内容(由于用于网络传输,所以是rb模式),并且发送给客户端
            # with open('%s/%s' %(SHARE_DIR, filename), 'rb') as f:  # 这里的文件路径拼接方式,容易出错,最好用os.path.join()
            # 因为os.path.join()拼接,无论目录路径是否最后有 / 都可以拼接成功。
            with open(os.path.join(SHARE_DIR, filename), 'rb') as f:

                # conn.send(f.read())  # 如果文件很大,内存会占满
                for line in f:  # 这样更加节省内存
                    conn.send(line)

        except ConnectionResetError as e:
            print(e)
            break
    conn.close()

server.close()

client.py

import socket
import struct
import json
import os.path

# 定义下载的目录路径,注意:这部分一般应该写在配置文件中
DOWNLOAD_DIR = r'C:\download'

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

client.connect(('127.0.0.1', 8080))  # 连接服务器IP和端口

while True:
    # 发命令
    cmd = input(">>>>:").strip()
    if not cmd:continue
    client.send(cmd.encode('utf-8'))

    # 接受服务器发来的文件内容,以write模式打开新文件,接受服务端发来的文件内容并写入
    # 第一步:先收报头长度(4bytes)的数据
    obj = client.recv(4)  # 接收服务器发来的,由struct打包的4bytes包
    header_size = struct.unpack('i', obj)[0]  # 解包,获得报头长度

    # 第二部:收报头
    header_bytes = client.recv(header_size)  # 根据报头长度收报头

    # 第三部:从报头中解析出真实数据的描述信息
    header_json = header_bytes.decode('utf-8')
    header_dic = json.loads(header_json)
    total_size = header_dic['total_size']
    filename = header_dic['filename']

    # 第四部:接受真实收据
    with open(os.path.join(DOWNLOAD_DIR, filename), 'wb') as f:
        recv_size = 0
        while recv_size < total_size:  # 循环直到收完指定长度的包
            line = client.recv(1024)
            f.write(line)
            recv_size += len(line)
            print('总大小%s,已经下载%s' % (total_size, recv_size))  # 这样我们可以知道进度

client.close()

上传功能的原理也是一样的

第八章 socket网络编程(10):文件传输功能的实现

原文:https://www.cnblogs.com/py-xiaoqiang/p/11299009.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!