首页 » 编程 » Python » Python学习 » 网络编程 » 正文

文件传输

简单的文件传输功能

目录结构:

 

server.py

import socket
import os
import json
import struct

IP = "127.0.0.1"
PORT = 9090
SHAR_DIR = r"D:\PycharmProjects\python_fullstack_middle\第三模块·面向对象&网络编程基础\第2章·网络编程\05_文件传输\server\share"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((IP, PORT))
server.listen(5)

while True:
    print("等待连接...")
    conn, client_addr = server.accept()
    print("客户端已建立连接,客户端地址为:", client_addr)

    while True:
        try:
            # 1. 收命令
            res = conn.recv(1024)
            if not res: break  # 适用于Linux系统

            # 2. 解析命令,提取相应命令的参数
            cmds = res.decode("utf-8").split()
            filename = cmds[1]

            # 3. 已读的方式打开文件,读取文件内容发送给客户端
            # 第一步:制作固定长度的报头
            head_dict = {
                "filename": filename,
                "md5": "xxxx",
                "filesize": os.path.getsize("%s/%s" % (SHAR_DIR, filename))
            }
            head_json = json.dumps(head_dict)
            head_bytes = head_json.encode("utf-8")

            # 第二步:先发送报头的长度
            conn.send(struct.pack('i', len(head_bytes)))

            # 第三步:再发报头
            conn.send(head_bytes)

            # 第四步:再发送真实的数据
            with open("%s/%s" % (SHAR_DIR, filename), "rb") as f:
                for line in f:
                    conn.send(line)

        except ConnectionResetError:  # 适用于Windows系统
            break
    conn.close()
server.close()

 

client.py

import socket
import struct
import json

IP = "127.0.0.1"
PORT = 9090
DOWNLOAD_DIR = r"D:\PycharmProjects\python_fullstack_middle\第三模块·面向对象&网络编程基础\第2章·网络编程\05_文件传输\client\download"
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((IP, PORT))

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

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

    # 第二步:再收报头
    head_bytes = client.recv(head_size)

    # 第三步:从报头中解析出对真实数据的描述信息
    head_json = head_bytes.decode("utf-8")
    head_dict = json.loads(head_json)
    print(head_dict)
    total_size = head_dict["filesize"]
    filename = head_dict["filename"]

    # 第四步:接收真实数据
    with open("%s/%s" % (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()

运行结果:

 

文件传输-函数版

改造为函数版,可实现  get, put 功能。

目录结构:

 

server.py

import socket
import os
import json
import struct

IP = "127.0.0.1"
PORT = 9090
SHARE_DIR = r"D:\PycharmProjects\python_fullstack_middle\第三模块·面向对象&网络编程基础\第2章·网络编程\05_文件传输-01函数版\server\share"


def get(conn, cmds):
    filename = cmds[1]

    # 3. 已读的方式打开文件,读取文件内容发送给客户端
    # 第一步:制作固定长度的报头
    head_dict = {
        "filename": filename,
        "md5": "xxxx",
        "filesize": os.path.getsize("%s/%s" % (SHARE_DIR, filename))
    }
    head_json = json.dumps(head_dict)
    head_bytes = head_json.encode("utf-8")

    # 第二步:先发送报头的长度
    conn.send(struct.pack('i', len(head_bytes)))

    # 第三步:再发报头
    conn.send(head_bytes)

    # 第四步:再发送真实的数据
    with open("%s/%s" % (SHARE_DIR, filename), "rb") as f:
        for line in f:
            conn.send(line)


def put(conn, cmds):
    print(cmds)
    conn.send("ok".encode("utf-8"))

    obj = conn.recv(4)
    head_size = struct.unpack("i", obj)[0]

    head_bytes = conn.recv(head_size)
    head_json = head_bytes.decode("utf-8")
    head_dict = json.loads(head_json)
    print(head_dict)
    total_size = head_dict["filesize"]
    filename = head_dict["filename"]

    # 第四步:接收真实数据
    with open("%s/%s" % (SHARE_DIR, filename), "wb") as f:
        recv_size = 0
        while recv_size < total_size:
            line = conn.recv(1024)
            f.write(line)
            recv_size += len(line)
            print("文件总大小:%s ,已接收:%s" % (total_size, recv_size))


def run():
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind((IP, PORT))
    server.listen(5)
    while True:
        print("等待连接...")
        conn, client_addr = server.accept()
        print("客户端已建立连接,客户端地址为:", client_addr)
        while True:
            try:
                # 1. 收命令
                res = conn.recv(1024)
                if not res: break  # 适用于Linux系统

                # 2. 解析命令,提取相应命令的参数
                cmds = res.decode("utf-8").split()
                if cmds[0] == "get":
                    get(conn, cmds)
                if cmds[0] == "put":
                    put(conn, cmds)
            except ConnectionResetError:  # 适用于Windows系统
                break
        conn.close()
    server.close()


if __name__ == '__main__':
    run()

 

client.py

import socket
import struct
import json
import os
IP = "127.0.0.1"
PORT = 9090
DOWNLOAD_DIR = r"D:\PycharmProjects\python_fullstack_middle\第三模块·面向对象&网络编程基础\第2章·网络编程\05_文件传输-01函数版\client\download"


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

    # 第二步:再收报头
    head_bytes = client.recv(head_size)

    # 第三步:从报头中解析出对真实数据的描述信息
    head_json = head_bytes.decode("utf-8")
    head_dict = json.loads(head_json)
    print(head_dict)
    total_size = head_dict["filesize"]
    filename = head_dict["filename"]

    # 第四步:接收真实数据
    with open("%s/%s" % (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))


def put(client, cmds):
    res=client.recv(1024)
    if res.decode("utf-8") == "ok":
        filename = cmds[1]

        head_dict = {
            "filename": filename,
            "md5": "xxxx",
            "filesize": os.path.getsize("%s/%s" % (DOWNLOAD_DIR, filename))
        }

        head_json = json.dumps(head_dict)
        head_bytes = head_json.encode("utf-8")

        # 第二步:先发送报头的长度
        client.send(struct.pack('i', len(head_bytes)))

        client.send(head_bytes)

        # 第四步:再发送真实的数据
        with open("%s/%s" % (DOWNLOAD_DIR, filename), "rb") as f:
            for line in f:
                client.send(line)



def run():
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect((IP, PORT))

    while True:
        # 1. 发命令
        inp = input(">>: ").strip()
        if not inp: continue
        client.send(inp.encode("utf-8"))
        cmds = inp.split()
        if cmds[0] == "get":
            get(client)
        if cmds[0] == "put":
            put(client, cmds)
    client.close()


if __name__ == '__main__':
    run()

 

文件传输-面向对象版

仅有put功能。

 

目录结构:

 

server.py  (进行了一些改变,原版在Windows上不能成功运行)

import socket
import struct
import json
import os


class FTPServer:
    address_family = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    allow_reuse_address = False
    max_packet_size = 8192
    coding = "utf-8"
    request_queue_size = 5
    AA = r"D:\PycharmProjects\python_fullstack_middle\第三模块·面向对象&网络编程基础\第2章·网络编程\05_文件传输-02面向对象版"
    server_dir = "file_upload"

    def __init__(self, server_address, bind_and_activate=True):
        self.server_address = server_address
        self.socket = socket.socket(self.address_family, self.socket_type)

        if bind_and_activate:
            try:
                self.server_bind()
                self.server_activate()
            except:
                self.server_close()
                raise

    def server_bind(self):
        if self.allow_reuse_address:
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.bind(self.server_address)
        self.server_address = self.socket.getsockname()  # ???

    def server_activate(self):
        self.socket.listen(self.request_queue_size)

    def server_close(self):
        self.socket.close()

    def get_request(self):
        return self.socket.accept()

    def close_request(self, request):
        request.close()

    def run(self):
        while True:
            self.conn, self.client_addr = self.get_request()
            print("from client: ", self.client_addr)
            while True:
                try:
                    head_struct = self.conn.recv(4)
                    print(head_struct)
                    if not head_struct: break

                    head_len = struct.unpack("i", head_struct)
                    print(head_len)
                    head_json = self.conn.recv(head_len[0]).decode(self.coding)
                    head_dic = json.loads(head_json)
                    print(head_dic)

                    cmd = head_dic["cmd"]
                    if hasattr(self, cmd):
                        getattr(self, cmd)(head_dic)
                except Exception:
                    break

    def put(self, args):
        print("come in..")
        file_path = os.path.normpath(os.path.join(self.AA, self.server_dir, args["filename"]))  # ??
        filesize = args["filesize"]
        recv_size = 0
        print("--->", file_path)
        dirname = os.path.dirname(file_path)
        if not os.path.exists(dirname):
            os.mkdir(dirname)

        with open(file_path, "wb") as f:
            print("11111")
            while recv_size < filesize:
                recv_data = self.conn.recv(self.max_packet_size)
                f.write(recv_data)
                recv_size += len(recv_data)
                print("recvsize:%s filesize:%s" % (recv_size, filesize))


tcpserver1 = FTPServer(("127.0.0.1", 8080))
tcpserver1.run()

 

client.py

import socket
import json
import os
import struct


class FTPClient:
    address_family = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    allow_reuse_address = False
    max_packet_size = 8192
    coding = "utf-8"
    requset_queue_size = 5

    def __init__(self, server_address, connect=True):
        self.server_address = server_address
        self.socket = socket.socket(self.address_family, self.socket_type)

        if connect:
            try:
                self.client_connect()
            except:
                self.client_close()
                raise

    def client_connect(self):
        self.socket.connect(self.server_address)

    def client_close(self):
        self.socket.close()

    def run(self):
        while True:
            inp = input(">>: ").strip()
            if not inp: continue
            l = inp.split()
            cmd = l[0]
            if hasattr(self, cmd):
                func = getattr(self, cmd)
                func(l)

    def put(self, args):
        cmd = args[0]
        filename = args[1]
        print(filename)
        if not os.path.isfile(filename):
            print("file:%s is not exists" % filename)
            return
        else:
            filesize = os.path.getsize(filename)

        head_dic = {"cmd": cmd, "filename": os.path.basename(filename), "filesize": filesize}  # ??
        print(head_dic)

        head_json = json.dumps(head_dic)
        head_json_bytes = bytes(head_json, encoding=self.coding)  # ??

        head_struct = struct.pack("i", len(head_json_bytes))
        self.socket.send(head_struct)
        self.socket.send(head_json_bytes)
        send_size = 0

        with open(filename, "rb") as f:
            for line in f:
                self.socket.send(line)
                send_size = + len(line)
                print("sendsize:%s " % send_size)
            else:
                print("upload successful")


client = FTPClient(('127.0.0.1', 8080))
client.run()

 

运行后在客户端输入: put test.mp4

 

赞 (0)

发表评论

*