美文网首页
socket传文件

socket传文件

作者: 狗狗胖妞 | 来源:发表于2017-06-14 18:19 被阅读44次

    粘包的两种处理方式

    • 一次完整的交互(ack响应)
    • 使用if判断,保证recv的最后一次,剩多少收多少(后面的数据就可再收了)

    get文件

    ftp server

    1. recv得到文件名
    2. 检测文件是否存在
    3. send文件大小给客户端(如果存在)
    4. 等待客户端确认
    5. 打开文件
    6. 边读边send,同时做MD5
    7. 最后send文件MD5
    8. 验证文件夹
    9. 关闭文件

    ftp client

    1. send 命令给server
    2. recv文件大小
    3. send something #一次交互解决粘包
    4. wb模式打开新文件
    5. 边recv边写,同时做md5
    6. 关闭文件
    7. recv服务端发过来的源文件的md5值

    在收完文件后又直接接收了md5的值,所以在收文件的过程中(f.close()之前),通过if判断,保证文件准确的接收了那么多

    get file 交互图


    import hashlib
    import socket,os
    server = socket.socket()
    server.bind(('localhost', 9999))
    server.listen()
    
    while True:
        conn,addr = server.accept()
        print('new conn:',addr)
        while True:
            print("等待新指令")
            data = conn.recv(1024)
            if not data:
                print("客户端已断开")
                break
    
            cmd,filename = data.decode().split()
            print(filename)
            if os.path.isfile(filename):
                f = open(filename, 'rb')
                m = hashlib.md5()
                file_size = os.stat(filename).st_size
                conn.send( str(file_size).encode() )  #send file size
                conn.recv(1024)   #等待确认
                for line in f:
                    m.update(line)
                    conn.send(line)
                print("file md5", m.hexdigest())
                f.close()
                conn.send(m.hexdigest().encode())
            print("send done")
    server.close()
    
    
    import socket
    import hashlib
    client = socket.socket()
    client.connect(('localhost', 9999))
    
    while True:
        cmd = input('>>:').strip()
        if not cmd:continue
        if cmd.startswith("get"):
            client.send(cmd.encode())
            server_response = client.recv(1024)
            print("server response:", server_response)
            client.send(b'ready to recv file')
            file_total_size = int(server_response.decode())
            received_size = 0
            filename = cmd.split()[1]
            f = open(filename+".new",'wb')
            m = hashlib.md5()
            while received_size < file_total_size:
                #如果没有此处if判断,可能会发生粘包(最后一次接受1024可能将md5一起收过来)
                if file_total_size - received_size > 1024:  #要收不止一次
                    size = 1024
                else:  #最后一次,剩多少收多少
                    size = file_total_size - received_size
                data = client.recv(size)    #用size替换1024
                received_size += len(data)
                m.update(data)
                f.write(data)
                print(file_total_size,received_size)
            else:
                new_file_md5 = m.hexdigest()
                print("file recv done")
                f.close()
            server_file_md5 = client.recv(1024)   #此处接收md5值(发生粘包客户端会在此处阻塞)
            print("server file md5:",server_file_md5)
            print("client file md5",new_file_md5)
    
    client.close()
    

    简单的ftp:https://github.com/jinboxu/ftp

    相关文章

      网友评论

          本文标题:socket传文件

          本文链接:https://www.haomeiwen.com/subject/hddsqxtx.html