`

python 网络(二、传输文件)

阅读更多

初衷

       先说一下我写这篇文章的初衷:很多时候,我需要在vmware workstation虚拟机我的物理机 之间传递信息,用U盘作为载体倒来倒去太麻烦。然而,一般来说我会在所有的系统中安装python(当然用C实现更保险,但是就需要.exe和ELF两个文件)。于是,我就想自己搞了一个python脚本,方便在这种“虚拟机和物理机”以及“虚拟机之间”的文件传递。

 

初次尝试

服务器:接收文件

# -*- coding: cp936 -*-
from socket import *
import struct
import os

ratio_base=0.00
def print_ratio(ratio, delta=1.00):
    global ratio_base
    if ratio > ratio_base + delta:
        ratio_base = ratio_base + delta
        print " %4.2f"%ratio,
        print "%"
    else:
        pass


if __name__ == "__main__":
    ADDR = ('127.0.0.1',8000)
    BUFSIZE = 1024

    FILEINFO_SIZE=struct.calcsize('128s32sI8s')

    recvSock = socket(AF_INET,SOCK_STREAM)
    recvSock.bind(ADDR)
    recvSock.listen(5)

    conn,addr = recvSock.accept()

    fhead = conn.recv(FILEINFO_SIZE)
    filename,temp1,filesize,temp2=struct.unpack('128s32sI8s',fhead)
    
    filename = filename.strip('\00') #???
    if os.path.isfile(filename):
        filename = raw_input("文件已存在,请起一个新名字[default: new_%s]  "%filename)
        if filename.strip() == "":
            filename = 'new_'+filename.strip('\00')
    else:
        filename = filename.strip('\00')
        
    
    fp = open(filename,'wb')

    restsize = filesize
    
    while True:
        if restsize > BUFSIZE:
            filedata = conn.recv(BUFSIZE)
        else:
            filedata = conn.recv(restsize)

        if not filedata:
            break

        fp.write(filedata)

        restsize = restsize-len(filedata)
        ratio = ( float(filesize) - float(restsize) ) / float(filesize) * 100

        print_ratio(ratio)

        if restsize == 0:
            break

    fp.close()
    conn.close()
    recvSock.close()
    print "received all"

 

 

 

客户端:传送文件

# -*- coding: cp936 -*-
from socket import *
import os
import struct

if __name__ == "__main__":
    ADDR = ('127.0.0.1',8000)
    BUFSIZE = 1024

    FILEINFO_SIZE=struct.calcsize('128s32sI8s')

    
    filename = raw_input("file to be sent under this dir: ")  #'贫民窟的百万富翁.rmvb'
    fhead=struct.pack('128s11I',filename,0,0,0,0,0,0,0,0,os.stat(filename).st_size,0,0)

    sendSock = socket(AF_INET,SOCK_STREAM)
    sendSock.connect(ADDR)
    sendSock.send(fhead)

    fp = open(filename,'rb')

    while True:
        filedata = fp.read(BUFSIZE)

        if not filedata:
            break

        sendSock.send(filedata)

    fp.close()
    sendSock.close()
    print "sent all"

 

浓缩成一个python脚本

 上面代码为了简洁起见,将客户端和服务器代码分离。但是为了部署方便,下面把他们做成一个文件

file_transer.py

# -*- coding: cp936 -*-
from socket import *
import struct
import os

ratio_base=0.00
def print_ratio(ratio, delta=1.00):
    global ratio_base
    if ratio > ratio_base + delta:
        ratio_base = ratio_base + delta
        print " %4.2f"%ratio,
        print "%"
    else:
        pass
    
def client_sender():
    print "current directory : ", os.getcwd()
    #print os.listdir(os.getcwd())
    server_ip = raw_input("receiver's ip : ")
    server_port = raw_input("receiver's port : ")
    
    ADDR = (server_ip, int(server_port) )
    BUFSIZE = 1024
    FILEINFO_SIZE=struct.calcsize('128s32sI8s')

    while True:
        try:
            filename = raw_input("file to be sent under this dir: ") #'贫民窟的百万富翁.rmvb'
            fhead=struct.pack('128s11I',filename,0,0,0,0,0,0,0,0,os.stat(filename).st_size,0,0)
            sendSock = socket(AF_INET,SOCK_STREAM)
            sendSock.connect(ADDR)
            sendSock.send(fhead)
            fp = open(filename,'rb')
            while True:
                filedata = fp.read(BUFSIZE)
                if not filedata:
                    break
                sendSock.send(filedata)
            fp.close()
            print "sent"
        except:
            print "sent error"
        
    sendSock.close()

def server_receiver():
    print "my ip : (ipconfig / ifconfig)"
    server_port = raw_input("my port : ")
    print "waiting for file ..."

    ADDR = ("", int(server_port))  #note: DO NOT USE "127.0.0.1"
    BUFSIZE = 1024
    FILEINFO_SIZE=struct.calcsize('128s32sI8s')
    recvSock = socket(AF_INET,SOCK_STREAM)
    recvSock.bind(ADDR)
    recvSock.listen(5)

    while True:
        try:
            conn,addr = recvSock.accept()
            fhead = conn.recv(FILEINFO_SIZE)
            filename,temp1,filesize,temp2=struct.unpack('128s32sI8s',fhead)
            filename = filename.strip('\00') #???
    
            if os.path.isfile(filename):
                filename = raw_input("文件已存在,请起一个新名字[default: new_%s] "%filename)
                if filename.strip() == "":
                    filename = 'new_'+filename.strip('\00')
                else:
                    filename = filename.strip('\00')
            fp = open(filename,'wb')
            restsize = filesize
            while True:
                if restsize > BUFSIZE:
                    filedata = conn.recv(BUFSIZE)
                else:
                    filedata = conn.recv(restsize)
                if not filedata:
                    break
                fp.write(filedata)
                restsize = restsize-len(filedata)
                ratio = ( float(filesize) - float(restsize) ) / float(filesize) * 100
                print_ratio(ratio)
                if restsize == 0:
                    break
            fp.close()
            conn.close()
            print filename, " received"
        except:
            print "receive error"
        
    recvSock.close()

if __name__ == "__main__":
    choice = raw_input("send or receive [s/r] : ")
    if choice == "s":
        client_sender()
        print
    elif choice == "r":
        server_receiver()
        print
    else:
        print "oops..."

 

有时间再完善下

       1. 目前不支持递归传递文件夹

       2. 目前不是多线程传输,速度还不够快(不过因为是单机上的传输影响不大)

       3. 目前只支持当前文件夹下的传输,最好允许指定路径

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics