网络编程(八)——实现文件传输功能

书读的越多而不加思考,你就会觉得你知道得很多;而当你读书而思考得越多的时候,你就会越清楚地看到,你知道得很少。

导读:本篇文章讲解 网络编程(八)——实现文件传输功能,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

实现文件传输功能

在通信循环中实现文件传输功能,以下载图片1.png为例,命令为:get 1.png

1、客户端发送命令:

cmd = input(">>:").strip() # get 1.png
    if not cmd:continue
    phone.send(cmd.encode("utf-8"))

2、服务端收命令:

res = conn.recv(8096)
        if not res:break

3、服务端解析命令:

        cmds = res.decode("utf-8").split() #得到['get','1.png']
        filename = cmds[1]

4、服务端以读的方式打开文件,读取文件内容发送给客户端:

  • 第一步:制作固定长度数据头
        header_dic = {
            "filename": filename,
            "md5": "xxxdxxx",
            'file_size': os.path.getsize(r"%s\%s"%(share_dir,filename))
        }
        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)
  • 第四步:再发送真实数据
        with open(("%s\%s"%(share_dir,filename)),"rb") as f:
            # conn.send(f.read())
            for line in f:
                conn.send(line) # 逐行读取再发送,有效节约系统内存,但是会粘包

5、 客户端以写的方式打开一个新的文件,接收服务端发来的文件的内容写入客户的新文件:

  • 第一步:先收数据头的长度
    obj = phone.recv(4) header_size = struct.unpack('i',obj)[0]
  • 第二步:再收数据头
    header_bytes = phone.recv(header_size)
  • 第三步:从数据头中解析出对真实数据的描述信息
    header_json = header_bytes.decode("utf-8") 
    header_dic = json.loads(header_json) 
    print(header_dic)
    # 查询数据头中包含的信息
    total_size = header_dic["file_size"] 
    filename = header_dic["filename"]
  • 第四步:接收真实的数据
    with open("%s\%s"%(download_dir,filename),"wb") as f:
        recv_size = 0
        while recv_size < total_size:
            line= phone.recv(1024)
            # 接收到一行就写入一行
            f.write(line)
            recv_size += len(line)
            print("总大小:%s 已经下载大小:%s"%(total_size,recv_size))

程序目录结构 

 网络编程(八)——实现文件传输功能

完整代码演示 

1、服务端代码

import socket
import subprocess
import struct
import json
import os

share_dir = r"E:\mydesktop\My_Code\后端\b站网络编程\05文件传输\server\share"

phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
phone.bind(("127.0.0.1",9910))
phone.listen(5)
print("starting...")

while True:
    conn,client_addr = phone.accept()
    print(client_addr)
    while True:
        # 1、收命令
        res = conn.recv(8096)
        if not res:break

        # 2、解析命令,提取相应命令参数
        cmds = res.decode("utf-8").split() #得到['get','a.txt']
        filename = cmds[1]

        # 3、以读的方式打开文件,读取文件内容发送给客户端
        # 第一步:制作固定长度的报头。
        header_dic = {
            "filename": filename,
            "md5": "xxxdxxx",
            'file_size': os.path.getsize(r"%s\%s"%(share_dir,filename))
        }
        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)

        # 第四步:再发送真实的数据
        with open(("%s\%s"%(share_dir,filename)),"rb") as f:
            # conn.send(f.read())
            for line in f:
                conn.send(line) # 逐行读取再发送,有效节约系统内存,但是会粘包

    conn.close()
phone.close()

2、客户端代码

import socket
import struct
import json

download_dir = r"E:\mydesktop\My_Code\后端\b站网络编程\05文件传输\client\Download"

phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(("127.0.0.1",9910))

while True:
    # 1、发命令
    cmd = input(">>:").strip() # get a.txt
    if not cmd:continue
    phone.send(cmd.encode("utf-8"))

    # 2、以写的方式打开一个新的文件,接收服务端发来的文件的内容写入客户的新文件
    # 第一步:先收报头的长度
    obj = phone.recv(4)
    header_size = struct.unpack('i',obj)[0]

    # 第二步:再收报头
    header_bytes = phone.recv(header_size)

    # 第三步:从数据头中解析出对真实数据的描述信息
    header_json = header_bytes.decode("utf-8")
    header_dic = json.loads(header_json)
    print(header_dic)
    # 查询数据头中包含的信息
    total_size = header_dic["file_size"]
    filename = header_dic["filename"]

    # 第四步:接收真实的数据
    with open("%s\%s"%(download_dir,filename),"wb") as f:
        recv_size = 0
        while recv_size < total_size:
            line= phone.recv(1024)
            # 接收到一行就写入一行
            f.write(line)
            recv_size += len(line)
            print("总大小:%s 已经下载大小:%s"%(total_size,recv_size))

phone.close()

3、先运行服务端,再运行客户端,在客户端控制台输入命令:get 1.png

1.png将被下载到Download目录下。 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/122896.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!