zoukankan      html  css  js  c++  java
  • socket传送文件

    一、文件传送步骤

      我们要利用socket来实现下载一个文件,该如何操作呢?

      服务端:

    1. 读取文件名
    2. 判断文件是否存在
    3. 检测文件大小(用于和客户端对比判断文件是否传送完毕)
    4. 发送文件大小给客户端
    5. 等待客户端确认(防止粘包)
    6. 打开文件
    7. 边读边发送数据
    8. md5验证

      客户端:

    • 发送命令
    • 接收文件大小
    • 返回确认
    • 获取文件名
    • 对比文件大小
    • 写入文件

    二、功能实现(ftp下载功能)

      服务端:

    # -*- coding: UTF-8 -*-
    import os
    import socket
    
    # TCP/IP协议, tcp ,如果不填写就是默认这个
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    server.bind(('localhost', 9999))
    
    server.listen()
    
    while True:  # 可以接受多个客户端
    
        conn, addr = server.accept()
        print('new conn', addr)
        while True:
    
            cmd_res = conn.recv(1024)
            if not cmd_res:   # 防止当接受的客户端数据为空时,程序卡掉
                print('client has lost...')
                break
            else:
                # 获取命令和文件名
                cmd, filename = cmd_res.decode().split()
                print(cmd, filename)
                if os.path.isfile(filename):  # 判断文件是否存在
                    # 文件大小
                    file_size = os.stat(filename).st_size
                    # 发送文件大小
                    conn.send(str(file_size).encode(encoding='utf-8'))
                    # 等待客户端确认
                    conn.recv(1024)
                    # 打开文件
                    f = open(filename, 'rb')
                    for line in f:
                        conn.send(line)
                        print('sending')
                    f.close()
    View Code

      客户端:

    # -*- coding: UTF-8 -*-
    import socket
    
    client = socket.socket()
    
    client.connect(('localhost', 9999))
    
    while True:
        cmd = input('>>:').strip()
        # 判断是否发送空数据,如果是就重新发送
        if len(cmd) == 0:
            continue
        else:
            client.send(cmd.encode('utf-8'))
            # 获取服务端发送的文件大小
            size = client.recv(1024)
            total_file_size = int(size.decode())
    
            # 返回确认
            client.send(b'file size received')
            filename = cmd.split()[1]
            print(filename)
            received_size = 0
            # 写入文件
            f = open(filename + '.new', 'w', encoding='utf-8')
            while received_size < total_file_size:
                r_data = client.recv(1024)
                received_size += len(r_data)
                f.write(r_data.decode() + '
    ')
            else:
                print('file sizes', total_file_size, received_size)
                print('receive finished')
                f.close()
    View Code

     有些问题 替换一些内容  

    f = open(filename + '.new', 'wb')
    f.write(r_data)

       

      这个程序有缺陷,首先目前只能读取本文件夹下的文件,新生成的文件没有中文乱码问题,ok...

    三、md5验证文件

      加个md5来验证文件是否一致

      服务端:

    # -*- coding: UTF-8 -*-
    import os
    import socket
    import hashlib
    
    # TCP/IP协议, tcp ,如果不填写就是默认这个
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
    server.bind(('localhost', 9999))
    
    server.listen()
    
    while True:  # 可以接受多个客户端
    
        conn, addr = server.accept()
        print('new conn', addr)
        while True:
    
            cmd_res = conn.recv(1024)
            if not cmd_res:   # 防止当接受的客户端数据为空时,程序卡掉
                print('client has lost...')
                break
            else:
                # md5
                m = hashlib.md5()
                # 获取命令和文件名
                cmd, filename = cmd_res.decode().split()
                print(cmd, filename)
                if os.path.isfile(filename):  # 判断文件是否存在
                    # 文件大小
                    file_size = os.stat(filename).st_size
                    print(file_size)
                    # 发送文件大小
                    conn.send(str(file_size).encode(encoding='utf-8'))
                    # 等待客户端确认
                    conn.recv(1024)
                    # 打开文件
                    f = open(filename, 'rb')
                    for line in f:
                        m.update(line)
                        # m.update('abc')  m.update('123')
                        # 其实和m.update('abc123') 结果一下
                        conn.send(line)
    
                    f.close()
                    print('send done')
                    # 发送md5信息
                    conn.send(m.hexdigest().encode('utf-8'))
    

      客户端:

    # -*- coding: UTF-8 -*-
    import socket
    import hashlib
    
    client = socket.socket()
    
    client.connect(('localhost', 9999))
    
    while True:
        cmd = input('>>:').strip()
        # 判断是否发送空数据,如果是就重新发送
        if len(cmd) == 0:
            continue
        else:
            client.send(cmd.encode('utf-8'))
            # 获取服务端发送的文件大小
            f_size = client.recv(1024)
            total_file_size = int(f_size.decode())
    
            # 返回确认
            client.send(b'file size received')
            filename = cmd.split()[1]
            print(filename)
            received_size = 0
            # md5
            m = hashlib.md5()
    
            # 写入文件
            f = open(filename + '.new', 'wb')  # 新生成的文件也正常显示
            while received_size < total_file_size:
                if total_file_size - received_size > 1024:  # 以此来控制只收文件的内容,不会粘包md5的内容
                    size = 1024
                else:
                    size = total_file_size - received_size
                r_data = client.recv(size)
                received_size += len(r_data)
                m.update(r_data)
                f.write(r_data)
                # print(r_data.decode())
                # print('file sizes', total_file_size, received_size)
            else:
                print('file sizes', total_file_size, received_size)
                server_md5 = client.recv(1024).decode()
                client_md5 = m.hexdigest()
                print(server_md5)
                print(client_md5)
                print('receive finished')
                f.close()
    

      结果:

      

      结果看上去没有问题了,新文件也能生成,并且有内容

  • 相关阅读:
    Java.io.outputstream.PrintStream:打印流
    Codeforces 732F. Tourist Reform (Tarjan缩点)
    退役了
    POJ 3281 Dining (最大流)
    Light oj 1233
    Light oj 1125
    HDU 5521 Meeting (最短路)
    Light oj 1095
    Light oj 1044
    HDU 3549 Flow Problem (dinic模版 && isap模版)
  • 原文地址:https://www.cnblogs.com/bigberg/p/7750182.html
Copyright © 2011-2022 走看看