初衷
先说一下我写这篇文章的初衷:很多时候,我需要在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脚本
扫描二维码关注公众号,回复:
1204608 查看本文章
上面代码为了简洁起见,将客户端和服务器代码分离。但是为了部署方便,下面把他们做成一个文件
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. 目前只支持当前文件夹下的传输,最好允许指定路径