文件传输

简单版

服务端

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
# Author:Mr.yang
import socket
import struct
import os
import json
import subprocess
share_dir=r'E:\Moudule_1\4.网络编程\5.文件传输\server\share'

'''
相对于简单版的优化
1.报头信息少
2.struct的i格式有限制
'''
def run():
    phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    phone.bind(('127.0.0.1',8080))
    phone.listen(5)

    print('setting...')
    while True: # 链接循环
        conn,A = phone.accept()
        while True: # 通信循环
            try:
                #1.接收数据
                res = conn.recv(8096) #b'get a.txt'
                print('客户端数据:',res)

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

                #3.以读的方式打开文件,读取文件内容发送给客户端
                #第一步: 制定固定长度的报头
                header_dic={
                    'filename': filename, #'filename':'a.txt'
                    'md5':'xxdxxx',
                    'file_size':os.path.getsize(r'%s/%s'%(share_dir,filename)) #os.path.getsize('E:\Moudule_1\4.网络编程\5.文件传输\server\share\a.txt')
                }

                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 ConnectionResetError:
                break
        conn.close
    phone.close()

客户端

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
# Author:Mr.yang
'''
recv不能设置数值特别大的原因:
1.在接收文件的时候可能超过指定数值
2.自己的操作系统的缓存不能无限大,最大也不能超过操作系统的缓存
'''
import socket
import struct
import json
download_dir = r'E:\Moudule_1\4.网络编程\5.文件传输\client\download'

phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
phone.connect(('127.0.0.1',8080))

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)
    '''
    header_dic={
                'filename': filename, #'filename':'a.txt'
                'md5':'xxdxxx',
                'file_size':os.path.getsize(filename)
            }
    '''
    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()

优化版

服务端

 

import socket
import struct
import os
import json
import subprocess

share_dir=r'E:\Moudule_1\4.网络编程\5.文件传输\优化版\server\share'

'''
相对于简单版的优化
1.报头信息少
2.struct的i格式有限制
'''
def get(conn,cmds):
    filename = cmds[1]

    # 3.以读的方式打开文件,读取文件内容发送给客户端
    # 第一步: 制定固定长度的报头
    header_dic = {
        'filename': filename,  # 'filename':'a.txt'
        'md5': 'xxdxxx',
        'file_size': os.path.getsize(r'%s/%s' % (share_dir, filename))
    # os.path.getsize('E:\Moudule_1\4.网络编程\5.文件传输\server\share\a.txt')
    }

    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 run():
    phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    phone.bind(('127.0.0.1',8080))
    phone.listen(5)

    print('setting...')
    while True: # 链接循环
        conn,A = phone.accept()
        while True: # 通信循环
            try:
                #1.接收数据
                res = conn.recv(8096) #b'get a.txt'
                print('客户端数据:',res)

                #2.解析命令,提取相应命令参数
                cmds = res.decode('utf-8').split() #['get','a.txt']
                if cmds[0] == 'get':
                    get(conn,cmds)
            except ConnectionResetError:
                break
        conn.close
    phone.close()

if __name__ == '__main__':
    run()

 

客户端

 

import socket
import struct
import json

download_dir = r'E:\Moudule_1\4.网络编程\5.文件传输\优化版\client\download'

def get(phone,cmds):
    # 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)
    '''
    header_dic={
                'filename': filename, #'filename':'a.txt'
                'md5':'xxdxxx',
                'file_size':os.path.getsize(filename)
            }
    '''
    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))


def run():
    phone = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    phone.connect(('127.0.0.1',8080))

    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)

    phone.close()

if __name__ == '__main__':
    run()

 

posted @ 2018-04-04 23:19  Mr。yang  阅读(233)  评论(0编辑  收藏  举报