Python-粘包、文件上传(ftp)

邮差的信 提交于 2020-03-06 11:57:11

粘包现象

  • 当多条信息发送时接受变成了一条或者出现接受不准确的情况

粘包现象会发生在发送端:

  • 两条消息间隔时间短,长度短,就会把两条消息在发送之前就拼在一起

  • 节省每一次发送消息回复的网络速度

粘包现象会发生在接收端:

  • 多条消息发送到缓存端,但没有被即使接受,或者接受的长度不足一次发送的长度

  • 数据与数据之间没有边界

本质:发送的每一条数据之间没有边界

struct

  • 能够把一个任意大小的数据转换成固定的4个字节

import structret = struct.pack('i', 1249519)print(ret)  # b'\xef\x10\x13\x00'​ret = struct.unpack('i', b'\xef\x10\x13\x00')rett1 = struct.unpack('i', b'\xef\x10\x13\x00')[0]print(ret)  # (1249519,)print(ret1)  # 1249519

文件上传(ftp)

服务端:

import socketimport structimport osimport jsonimport sysREMOTE_DIR = os.path.join(os.path.dirname(_file_), 'remote')​def myrecv(conn):    num_bytes = conn.recv(4)    msg_len = struct.unpack('i', num_bytes)[0]    json_dic = conn.recv(msg_len).decode('utf-8')    opt_dic = json.loads(json_dic)    return opt_dicdef mysend(conn, dic):    dic_bytes = json.dumps(dic).encode('utf-8')    num_bytes = struct.pack('i', len(dic_bytes))    conn.send(num_bytes)    conn.send(dic_bytes)def upload(conn):    filename = opt_dic['filename']    filesize = opt_dic['filesize']    filepath = os.path.join(REMOTE_DIR, filename)    with open(filepath, 'wb') as f:        while filesize > 0:            content = conn.recv(1024)            f.write(content)            filesize -= len(content)            # 要接受得字节数不一定是你实际接收到的数据长度def download(conn):    filepath = os.path.join(REMOTE_DIR, opt_dic['filename'])    if os.path.isfile(filepath):    # 判断是否存在这个文件        size = os.path.getsize(filepath)    # 返回文件大小        dic = {'filesize': size}        mysend(conn, dic)        with open(filepath, 'rb') as f:            while szie > 0:                content = f.read(4096)                conn.send(content)                size -= len(content)                                if __name__ = '__main__':    sk = socket.socket()    sk.bind(('127.0.0.1', 9000))    sk.listen()        conn, addr = accept()    opt_dic = myrecv(conn)        if hasattr(sys.modules[__name__], opt_dic['operate']):        getattr(sys.modules[__name__], opt_dic['operatee'])(conn)

客户端:

import socketimport osimport structimport jsonLOCAL_DIR  = os.path.join(os.path.dirname(__file__), 'local')​def mysend(sk, opt_dic):    opt_bytes = json.dumps(opt_dic).encode('utf-8')    num_bytes = struct.pack('i', len(opt_bytes))    sk.send(num_bytes)    sk.send(opt_bytes)def myrecv(sk):    bytes_len = sk.recv(4)    msg_len = struct.unpack('i', bytes_len)[0]    str_dic = sk.recv(msg_len).decode('utf-8')    size_dic = json.loads(str_dic)    return size_dic​def upload(sk):    path = input('请输入要上传的文件路径:')    # 用户输入要上传的文件    if os.path.isfile(path):    # 检查这个文件是否存在        filename = os.path.basename(path)   # 获取文件名        filesize = os.path.getsize(path)    # 获取文件大小        opt_dic = {'filename': filename, 'filesize': filesize, 'operate': 'upload'}        mysend(sk, opt_dic)        with open(path,'rb') as f:            while filesize > 0:                content = f.read(4096)                sk.send(content)                filesize -= len(content)def download(sk):    # remote文件夹中的所有文件都可以下载    filename = input('请输入要下载的文件名:')     # 用输入一个文件名    opt_dic = {'filename': filename, 'operate': 'download'}    mysend(sk, opt_dic)    size_dic = myrecv(sk)    filepath = os.path.join(LOCAL_DIR,filename)    with open(filepath, 'wb') as f:        while size_dic['filesize'] > 20:            content = sk.recv(1024)            f.write(content)            size_dic['filesize'] -= len(content)​if __name__ = '__main__':    sk = socket.socket()    sk.connect(('127.0.0.1',9000))    opt_lst = [('上传', upload), ('下载', download)]    for index, opt in enumerate(opt_lst, 1):        print(index, opt)    inp = int(input('>>>'))    opt_lst[inp-1][1](sk)

 

 

 

 

 

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!