文件传送

简单版

服务端

import socket
import subprocess
import struct
import json
import os

share_dir = r'F:\project\book\chapter6\文件传输\简单版本\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", 9909))   # 127.0.0.1本地地址,端口范围0-65535:其中0-1024给操作系统使用

phone.listen(5)   # 5代表最大挂起连接数

print("starting...")
while True:  # 循环链接
    conn, client = phone.accept()  # conn套接字对象

    while True:    # 通讯循环
        try:
            # 1、接收命令  (命令:执行系统命令)
            res = conn.recv(8096)  # b'get a.txt

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

            # 3、以读的方式打开文件,读取文件内容,发送给客户端

            # 第一步:制作固定长度的报头(import struct)
            header_dic = {
                "filename": filename,
                "md5": "xxdxxx",
                "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)

        except ConnectionRefusedError:
            break

    conn.close()

phone.close()

 客户端

import socket
import struct
import json

download_dir = r"F:\project\book\chapter6\文件传输\简单版本\client\download"

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

phone.connect(("127.0.0.1", 9909))  # phone相当于服务端的conn

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

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

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

    # 第三步:从报头中解析出对真实数据的描述信息
    header_json = header_bytes.decode("utf-8")
    header_dic = json.loads(header_json)
    print(header_dic)
    file_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 < file_size:
            line = phone.recv(1024)
            f.write(line)
            recv_size += len(line)
            print("总大小:%s  已下载大小:%s" % (file_size, recv_size))

phone.close()

  


函数版

服务端

import socket
import subprocess
import struct
import json
import os

share_dir = r'F:\project\book\chapter6\文件传输\函数版本\server\share'


def get(conn, cmds):
    filename = cmds[1]
    # 3、以读的方式打开文件,读取文件内容,发送给客户端
    # 第一步:制作固定长度的报头(import struct)
    header_dic = {
        "filename": filename,
        "md5": "xxdxxx",
        "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)


def put(conn, cmds):
    pass


def run():
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # (如果机器中存在,重新用端口)应对端口占用报错情况
    phone.bind(("127.0.0.1", 9909))   # 127.0.0.1本地地址,端口范围0-65535:其中0-1024给操作系统使用
    phone.listen(5)   # 5代表最大挂起连接数

    print("starting...")
    while True:  # 循环链接
        conn, client = phone.accept()  # conn套接字对象

        while True:    # 通讯循环
            try:
                # 1、接收命令  (命令:执行系统命令)
                res = conn.recv(8096)  # b'get a.txt

                # 2、解析命令,提取相应的命令参数
                cmds = res.decode("utf-8").split()
                if cmds[0] == "get":
                    get(conn, cmds)
                elif cmds[0] == "put":
                    put(conn, cmds)
            except ConnectionRefusedError:
                break

        conn.close()

    phone.close()


if __name__ == "__main__":   #如果是执行当前文件的时候,这个条件成立,就执行。如果当前文件被其他文件当成模块导入的时候,这个条件是不成立的,里面的代码是不执行的
    run()

 客户端

import socket
import struct
import json

download_dir = r"F:\project\book\chapter6\文件传输\函数版本\client\download"


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

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

    # 第三步:从报头中解析出对真实数据的描述信息
    header_json = header_bytes.decode("utf-8")
    header_dic = json.loads(header_json)
    print(header_dic)
    file_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 < file_size:
            line = phone.recv(1024)
            f.write(line)
            recv_size += len(line)
            print("总大小:%s  已下载大小:%s" % (file_size, recv_size))


def put(phone, cmds):
    pass


def run():
    phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    phone.connect(("127.0.0.1", 9909))  # phone相当于服务端的conn

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


if __name__ == "__main__":   # 如果是执行当前文件的时候,这个条件成立,就执行。如果当前文件被其他文件当成模块导入的时候,这个条件是不成立的,里面的代码是不执行的
    run()

  


类版本

服务端

import socket
import subprocess
import struct
import json
import os

# 面相对象的好处可以把数据和操作数据的方法整合到一起


class MYServer:
    address_family = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    max_packet_size = 8192
    coding = "utf-8"
    request_queue_size = 5
    allow_reuse_address = False    # 允许地址再用
    server_dir = r"F:\project\book\chapter6\文件传输\函数版本\server\share"

    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 EOFError:
                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()  # 本机的IP和端口号

    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()  # conn套接字对象
            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)       # path
                    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 ConnectionRefusedError:
                    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))

    def get(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)


server = MYServer(('127.0.0.1', 8080))
server.run()

客户端

import socket
import struct
import json
import os


class MYClient:
    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 EOFError:
                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')

def get(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))
        else:
            print('download successful')


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

  

 

posted @ 2018-12-01 22:08  混世妖精  阅读(225)  评论(0编辑  收藏  举报