zoukankan      html  css  js  c++  java
  • Python Socket实现文件上传(TCP协议)

    在TCP协议下通过socket模块实现文件上传

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # desc: tcp_server_file_upload
    
    import socket
    import struct
    import json
    import time
    
    IP_PORT    = ('127.0.0.1', 8080)
    BUFFERSIZE = 1024
    
    tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  #获取socket对象,并设置通过TCP协议通信
    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)#设置连接重用
    tcp_server_socket.bind(IP_PORT) #绑定IP地址和端口
    tcp_server_socket.listen()      #监听,可指定数量
    
    conn, addr = tcp_server_socket.accept() #建立连接
    print('client ip addr:', addr)
    head_struct = conn.recv(4)  #接收定制报头的长度
    head_json_len = struct.unpack('i', head_struct)[0]   #解包,获取定制报头的长度
    head_json = conn.recv(head_json_len).decode('utf-8') #根据上一步解包获得的报头长度,接收报头
    head = json.loads(head_json) #将json字符串类型的报头转化为python对象
    file_size = head['file_size']#获取待接收文件的大小
    file_name = head['file_name']#获取接收文件的名字
    print(time.strftime('%Y-%m-%d %H:%M:%S'),' 开始接收文件...') #打印开始接收文件的时间
    with open(file_name, 'wb') as f:  #以二进制写方式打开文件
        '''
        循环写入接收的文件内容
        '''
        while True:
            if file_size >= BUFFERSIZE:   #如果接收的文件内容大于设置的BUFFERSIZE,就只接收BUFFERSIZE大小的内容
                content = conn.recv(BUFFERSIZE) #接收客服端发送的BUFFERSIZE大小的内容
                f.write(content) #在服务端写入BUFFERSIZE大小的内容
                file_size -= BUFFERSIZE #将待写入的文件大小减去已接收的BUFFERSIZE大小
                '''
                主要是用于服务端和客户端在同一PC上,且写入比读取快,从而导致服务端先行关闭,
                造成客户端连接中断,文件传送不完整
                '''
                time.sleep(0.00001) 
            else:
                content = conn.recv(file_size) #接收文件剩余部分
                f.write(content)
                break
    print(time.strftime('%Y-%m-%d %H:%M:%S'),' 成功接收文件...') #打印文件接收完成时间
    
    conn.close() #关闭连接
    tcp_server_socket.close() #关闭服务端socket
    tcp_server_file_upload
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    # @desc: tcp_client_file_upload
    
    import socket
    import struct
    import json
    import os
    import time
    
    IP_PORT    = ('127.0.0.1', 8080)
    BUFFERSIZE = 1024
    
    tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #获取socket对象
    tcp_client_socket.connect(IP_PORT) #连接服务端
    
    '''
    定制化报头
    '''
    head = {'file_path':r'文件路径',
            'file_name':r'文件名',
            'file_size':0
            }
    
    file_path = os.path.join(head['file_path'], head['file_name']) #获取要上传文件的完整路径
    file_size = os.path.getsize(file_path) #获取文件大小
    head['file_size'] = file_size #将获取到的真实文件大小设置到报头
    
    head_json = json.dumps(head)  #将报头python对象转化为json字符串
    head_bytes = bytes(head_json, encoding='utf-8') #将报头json字符串转化为bytes字节码
    head_struct = struct.pack('i', len(head_bytes)) #将报头bytes字节码以'integer'类型打包为4个字节
    tcp_client_socket.send(head_struct) #发送打包为4个字节的报头
    tcp_client_socket.send(head_bytes)  #发送定制化报头
    print(time.strftime('%Y-%m-%d %H:%M:%S'),' 开始发送文件...') #打印开始发送文件的时间
    with open(file_path, 'rb') as f:    #以二进制读的方式打开文件
        '''
        循环读取文件内容并发送给服务端
        '''
        while True:
            if file_size >= BUFFERSIZE: #如果发送文件的大小大于BUFFERSIZE,只读取BUFFERSIZE大小的内容
                content = f.read(BUFFERSIZE) #读取BUFFERSIZE大小的内容
                tcp_client_socket.sendall(content) #发送读取的文件内容
                file_size -= BUFFERSIZE #文件大小减去已发送文件的大小
            else:
                content = f.read(file_size)  #读取剩余文件内容
                tcp_client_socket.sendall(content) #发送文件读取的文件内容
                break #终止循环
    
    print(time.strftime('%Y-%m-%d %H:%M:%S'),' 文件发送成功...') #大于文件发送完成的时间
    tcp_client_socket.close() #关闭socket
    tcp_client_file_upload
  • 相关阅读:
    linq获取最大ID值
    asp:MultiView选项卡控件,可以用来选择性的显示需要的部门
    TFS修改工作区映射区
    怎么解决javascript小数相减会出现一长串的小数位数?
    (转)向页面动态载入用户控件和自定义控件的方法(谨记)
    (转)工作经验到底是个什么东东?工作经验从哪里来?
    hdu 5441 travel 离线+带权并查集
    hdu 5438 Ponds dfs
    hdu 5437 Alisha’s Party 模拟 优先队列
    CF 500 B. New Year Permutation 并查集
  • 原文地址:https://www.cnblogs.com/yueyun00/p/10027033.html
Copyright © 2011-2022 走看看