17 [网络编程]-文件传输

1.通过socket收发文件软件开发

1、客户端提交命令

2、服务端接收命令,解析,执行下载文件的方法,即以读的方式打开文件,for循环读出文件的一行行内容,然后send给客户端

3、客户端以写的方式打开文件,将接收的内容写入文件中

  

2、文件传输普通版

  (1)服务端

import socket
import struct
import subprocess
import json
import os


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

server.bind(('127.0.0.1', 9994))

server.listen(5)

while True:
    print('waiting...')
    conn, addr = server.accept()

    while True:
        try:
            cmds = conn.recv(1024)   # get a.txt
            print('=》', cmds)
            if not cmds:
                break

            # 提取出相应的命令参数

            filename = cmds.decode('utf-8').split()[1]
            print(filename)
            # 以读的方式打开文件,将数据一点点发送给客户端

            # 第一步:制作报头
            header_dict = {
                'filename': filename,
                'md5': 'afdsafsaf',
                'total_size': os.path.getsize(filename)
            }
            header_json = json.dumps(header_dict)  # 报头的json样式
            header_bytes = header_json.encode('utf-8')          # 报头---报头.json---报头.bytes

            # 发送报头的长度
            header_len = struct.pack('i', len(header_bytes))    # 报头bytes---> len()---> struct
            conn.send(header_len)

            # 第二部:把报头发送给客户端
            conn.send(header_bytes)

            # 第三部:发送真实数据
            with open(filename, 'rb') as f:
                for line in f:
                    conn.send(line)

        except ConnectionResetError:
            break

    conn.close()


server.close()

  (2)客户端

import socket
import struct
import json

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

client.connect(('127.0.0.1', 9994))

while True:

    data = input('>>>').strip()         # get a.txt
    if not data:
        continue
    client.send(data.encode('utf-8'))

    # 以写的方式,打开一个新文件,接受服务端传来的文件内容,写入新文件

    # 2.接受报头的长度
    header_bytes_len = client.recv(1024)
    header_bytes_len = struct.unpack('i', header_bytes_len)[0]

    # 接收报头的json数据
    header_bytes = client.recv(header_bytes_len)
    print(header_bytes)

    # 3.从报头中解析出对真实数据的描述信息(数据的长度)
    header_json = header_bytes.decode('utf-8')
    header_dict = json.loads(header_json)

    total_size = header_dict['total_size']
    filename = header_dict['filename']
    # 3.一段段的取数据

    # 4.打开文件,写入内容

    new_file = "%s.bak" % filename
    with open(new_file, 'wb') as f:
        recv_size = 0
        while recv_size < total_size:  # 接受的数据长度 = len(total_data) 已经取完了,就退出
            data = client.recv(1024)
            f.write(data)
            recv_size += len(data)

client.close()

3、文件传输:拼接路径版本

   

import socket
import struct
import subprocess
import json
import os


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

server.bind(('127.0.0.1', 9994))

server.listen(5)

while True:
    print('waiting...')
    conn, addr = server.accept()

    while True:
        try:
            cmds = conn.recv(1024)   # get a.txt
            print('=》', cmds)
            if not cmds:
                break

            # 提取出相应的命令参数

            filename = cmds.decode('utf-8').split()[1]   # 获取basename
            print(filename)
            # 绝对路径拼接
            SERVER_PATH = os.path.dirname(os.path.abspath(__file__))
            FILE_PATH = os.path.join(os.path.join(SERVER_PATH, 'share'), filename)

            # 以读的方式打开文件,将数据一点点发送给客户端

            # 第一步:制作报头
            header_dict = {
                'filename': FILE_PATH,
                'md5': 'afdsafsaf',
                'total_size': os.path.getsize(FILE_PATH)
            }
            header_json = json.dumps(header_dict)  # 报头的json样式
            header_bytes = header_json.encode('utf-8')          # 报头---报头.json---报头.bytes

            # 发送报头的长度
            header_len = struct.pack('i', len(header_bytes))    # 报头bytes---> len()---> struct
            conn.send(header_len)

            # 第二部:把报头发送给客户端
            conn.send(header_bytes)

            # 第三部:发送真实数据
            with open(FILE_PATH, 'rb') as f:
                for line in f:
                    conn.send(line)

        except ConnectionResetError:
            break

    conn.close()


server.close()
服务端
import socket
import os
import struct
import json

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

client.connect(('127.0.0.1', 9994))

while True:

    data = input('>>>').strip()         # get a.txt
    if not data:
        continue
    client.send(data.encode('utf-8'))

    # 以写的方式,打开一个新文件,接受服务端传来的文件内容,写入新文件

    # 2.接受报头的长度
    header_bytes_len = client.recv(1024)
    header_bytes_len = struct.unpack('i', header_bytes_len)[0]

    # 接收报头的json数据
    header_bytes = client.recv(header_bytes_len)

    # 3.从报头中解析出对真实数据的描述信息(数据的长度)
    header_json = header_bytes.decode('utf-8')
    header_dict = json.loads(header_json)

    total_size = header_dict['total_size']
    filename = header_dict['filename']
    # 3.一段段的取数据

    # 4.打开文件,写入内容, 文件路径修改
    CLIENT_PATH = os.path.dirname(os.path.abspath(__file__))
    FILE_PATH = os.path.join(os.path.join(CLIENT_PATH, 'download'), os.path.basename(filename))

    with open(FILE_PATH, 'wb') as f:
        recv_size = 0
        while recv_size < total_size:  # 接受的数据长度 = len(total_data) 已经取完了,就退出
            data = client.recv(1024)  
            f.write(data)
            recv_size += len(data)
            print("总共%s bytes 已经传输%s bytes" %(total_size,recv_size))   # 简易进度条
client.close()
客户端

    

  •   pycharm 显示目录延迟!

4、函数版本:上传,下载功能

  (1)服务端

import socket
import struct
import subprocess
import json
import os


def get(cmds, conn):
    filename = cmds.decode('utf-8').split()[1]  # 获取basename

    # 绝对路径拼接
    SERVER_PATH = os.path.dirname(os.path.abspath(__file__))
    FILE_PATH = os.path.join(os.path.join(SERVER_PATH, 'share'), filename)

    # 以读的方式打开文件,将数据一点点发送给客户端

    # 第一步:制作报头
    header_dict = {
        'filename': FILE_PATH,
        'md5': 'afdsafsaf',
        'total_size': os.path.getsize(FILE_PATH)
    }
    header_json = json.dumps(header_dict)  # 报头的json样式
    header_bytes = header_json.encode('utf-8')  # 报头---报头.json---报头.bytes

    # 发送报头的长度
    header_len = struct.pack('i', len(header_bytes))  # 报头bytes---> len()---> struct
    conn.send(header_len)

    # 第二部:把报头发送给客户端
    conn.send(header_bytes)

    # 第三部:发送真实数据
    with open(FILE_PATH, 'rb') as f:
        for line in f:
            conn.send(line)


def put(client):
    # 2.接受报头的长度
    header_bytes_len = client.recv(1024)
    header_bytes_len = struct.unpack('i', header_bytes_len)[0]

    # 接收报头的json数据
    header_bytes = client.recv(header_bytes_len)

    # 3.从报头中解析出对真实数据的描述信息(数据的长度)
    header_json = header_bytes.decode('utf-8')
    header_dict = json.loads(header_json)

    total_size = header_dict['total_size']
    filename = header_dict['filename']
    # 3.一段段的取数据

    # 4.打开文件,写入内容, 文件路径修改
    CLIENT_PATH = os.path.dirname(os.path.abspath(__file__))
    FILE_PATH = os.path.join(os.path.join(CLIENT_PATH, 'share'), os.path.basename(filename))

    with open(FILE_PATH, 'wb') as f:
        recv_size = 0
        while recv_size < total_size:  # 接受的数据长度 = len(total_data) 已经取完了,就退出
            data = client.recv(1024)
            f.write(data)
            recv_size += len(data)
            print("总共%s bytes 已经传输%s bytes" % (total_size, recv_size))  # 简易进度条


def main():
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind(('127.0.0.1', 9994))
    server.listen(5)
    while True:
        print('waiting...')
        conn, addr = server.accept()
        while True:
            try:
                cmds = conn.recv(1024)   # get a.txt
                print('=》', cmds)
                if not cmds:
                    break

                # 提取出相应的命令参数
                cmd_type = cmds.decode('utf-8').split()[0]
                if cmd_type == 'get':
                    get(cmds, conn)

                elif cmd_type == 'put':
                    put(conn)

            except ConnectionResetError:
                break

        conn.close()


    server.close()

if __name__ == '__main__':
    main()

  

  (2)客户端

import socket
import os
import struct
import json


def get(client):
    # 以写的方式,打开一个新文件,接受服务端传来的文件内容,写入新文件

    # 2.接受报头的长度
    header_bytes_len = client.recv(1024)
    header_bytes_len = struct.unpack('i', header_bytes_len)[0]

    # 接收报头的json数据
    header_bytes = client.recv(header_bytes_len)

    # 3.从报头中解析出对真实数据的描述信息(数据的长度)
    header_json = header_bytes.decode('utf-8')
    header_dict = json.loads(header_json)

    total_size = header_dict['total_size']
    filename = header_dict['filename']
    # 3.一段段的取数据

    # 4.打开文件,写入内容, 文件路径修改
    CLIENT_PATH = os.path.dirname(os.path.abspath(__file__))
    FILE_PATH = os.path.join(os.path.join(CLIENT_PATH, 'download'), os.path.basename(filename))

    with open(FILE_PATH, 'wb') as f:
        recv_size = 0
        while recv_size < total_size:  # 接受的数据长度 = len(total_data) 已经取完了,就退出
            data = client.recv(1024)
            f.write(data)
            recv_size += len(data)
            print("总共%s bytes 已经传输%s bytes" % (total_size, recv_size))  # 简易进度条


def put(cmds,client):

    # 文件路径拼接
    filename = cmds.split()[1]  # 获取basename
    CLIENT_PATH = os.path.dirname(os.path.abspath(__file__))
    FILE_PATH = os.path.join(os.path.join(CLIENT_PATH, 'download'), filename)
    if not os.path.isfile(FILE_PATH):
        print('this file is not find')
        return
    # 1.找出file的绝对路径

    # 2.读取文件的size
    header_dict = {
        'filename': FILE_PATH,
        'md5': 'dffsaf',
        'total_size': os.path.getsize(FILE_PATH),
    }

    # 3.传输报头
    header_json = json.dumps(header_dict)
    header_bytes = header_json.encode('utf-8')
    header_len = struct.pack('i', len(header_bytes))
    client.send(header_len)

    client.send(header_bytes)

    # 4.打开文件读取内容,并传输
    with open(FILE_PATH, 'rb') as f:
        for line in f:
            client.send(line)



def main():
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect(('127.0.0.1', 9994))

    while True:
        cmds = input('>>>').strip()
        if not cmds:
            continue
        client.send(cmds.encode('utf-8'))

        cmd_type = cmds.split()[0]
        if cmd_type == 'get':
            get(client)

        elif cmd_type == 'put':
            put(cmds,client)

    client.close()

if __name__ == '__main__':
    main()

    

5、面向对象,类:文件传输

  • 自己写的
import socket
import struct
import subprocess
import json
import os


class Server(object):

    def __init__(self,ip,port):
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.ip = ip
        self.port = port

    def run(self):
        self.bind()
        self.listen()
        while True:
            print('waiting...')
            conn, addr = self.accept()
            print(conn, addr)
            while True:
                try:
                    cmds = self.recv(conn)
                    print('=》', cmds)
                    if not cmds:
                        break

                    self.get(cmds, conn)

                except ConnectionResetError:
                    break

            conn.close()

        self.socket.close()

    def bind(self):
        self.socket.bind((self.ip, self.port))

    def listen(self,):
        self.socket.listen(5)

    def accept(self):
        conn, addr = self.socket.accept()
        return conn, addr

    def recv(self,conn):
        cmds = conn.recv(1024)
        return cmds

    def get(self,cmds, conn):
        filename = cmds.decode('utf-8').split()[1]

        SERVER_PATH = os.path.dirname(os.path.abspath(__file__))
        FILE_PATH = os.path.join(os.path.join(SERVER_PATH, 'share'), filename)

        header_dict = {
            'filename': FILE_PATH,
            'md5': 'afdsafsaf',
            'total_size': os.path.getsize(FILE_PATH)
        }
        header_json = json.dumps(header_dict)
        header_bytes = header_json.encode('utf-8')

        header_len = struct.pack('i', len(header_bytes))
        conn.send(header_len)

        conn.send(header_bytes)

        with open(FILE_PATH, 'rb') as f:
            for line in f:
                conn.send(line)

server = Server('127.0.0.1', 9994)
server.run()
服务端
import socket
import os
import struct
import json


class Client(object):

    def __init__(self,ip,port):
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.ip = ip
        self.port = port

    def run(self):
        self.connect()
        while True:
            data = input('>>>').strip()
            if not data:
                continue
            self.client.send(data.encode('utf-8'))
            self.get()
        self.client.close()

    def connect(self):
        self.client.connect((self.ip, self.port))

    def get(self):
        header_bytes_len = self.client.recv(1024)
        header_bytes_len = struct.unpack('i', header_bytes_len)[0]
        header_bytes = self.client.recv(header_bytes_len)

        header_json = header_bytes.decode('utf-8')
        header_dict = json.loads(header_json)

        total_size = header_dict['total_size']
        filename = header_dict['filename']

        CLIENT_PATH = os.path.dirname(os.path.abspath(__file__))
        FILE_PATH = os.path.join(os.path.join(CLIENT_PATH, 'download'), os.path.basename(filename))

        with open(FILE_PATH, 'wb') as f:
            recv_size = 0
            while recv_size < total_size:  # 接受的数据长度 = len(total_data) 已经取完了,就退出
                data = self.client.recv(1024)
                f.write(data)
                recv_size += len(data)
                print("总共%s bytes 已经传输%s bytes" % (total_size, recv_size))  # 简易进度条


client = Client('127.0.0.1',9994)
client.run()
客户端
  • 老师写的
import socket
import struct
import json
import subprocess
import os

class MYTCPServer:
    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

    server_dir='file_upload'

    def __init__(self, server_address, bind_and_activate=True):
        """Constructor.  May be extended, do not override."""
        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):
        """Called by constructor to bind the socket.
        """
        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):
        """Called by constructor to activate the server.
        """
        self.socket.listen(self.request_queue_size)

    def server_close(self):
        """Called to clean-up the server.
        """
        self.socket.close()

    def get_request(self):
        """Get the request and client address from the socket.
        """
        return self.socket.accept()

    def close_request(self, request):
        """Called to clean up an individual 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)
                    if not head_struct:break

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

                    print(head_dic)
                    #head_dic={'cmd':'put','filename':'a.txt','filesize':123123}
                    cmd=head_dic['cmd']
                    if hasattr(self,cmd):
                        func=getattr(self,cmd)
                        func(head_dic)
                except Exception:
                    break

    def put(self,args):
        file_path=os.path.normpath(os.path.join(
            self.server_dir,
            args['filename']
        ))

        filesize=args['filesize']
        recv_size=0
        print('----->',file_path)
        with open(file_path,'wb') as f:
            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=MYTCPServer(('127.0.0.1',8080))

tcpserver1.run()
服务端实现
import socket
import struct
import json
import os



class MYTCPClient:
    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

    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]
        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(send_size)
            else:
                print('upload successful')




client=MYTCPClient(('127.0.0.1',8080))

client.run()
客户端实现
原文地址:https://www.cnblogs.com/venicid/p/8679516.html