Sending File Over Python Socket - Hanging at socket.sendall -
i've written thought simple script download files on network python sockets, server hangs on socket.sendall on server side. can file want once, subsequent calls senddata cause crash.
after looking bit more, i'm sure it's how i'm packing header data, meaning may low-level issue beyond ken.
for context: 'master' code running on x86 computer, while 'slave' code running on raspberry pi 0 (arm).
the header's defined in code, here's overview:
- file length , length of filename bundled 8-byte header of 2 uints.
- filename , first chunk of (h264 video) data bundled 1kb initial send.
- the server sends further data in 1kb chunks until it's sent whole file.
i'm pretty puzzled why doesn't work seems routine bit of code.
slave (server)
#takes filename , sends data connected socket def senddata(filename,socket): try: filehandle = open(filename,'rb') except ioerror: socket.sendall('abort') print 'file ' +filename+ ' not found; not sending...' else: #writes 8 byte header consisting of: #length of file (including filename) in kb (4b) #length of filename (4b) numbytes = struct.pack("<i",math.ceil((os.stat(filename).st_size + len(filename)) / 1024)) #amount of kb (1024) receive, written 4-byte integer filenamebytes = struct.pack("<i",len(filename)) print 'sending '+filename+'...' socket.sendall(numbytes + filenamebytes) data = filename + filehandle.read(1024 - len(filename)) while true: socket.sendall(data) data = filehandle.read(1024) if not data: break filehandle.close() print 'send complete.'
master (client)
def receivedownload(socket): #gets header data = socket.recv(8) if data != 'abort': filekb = struct.unpack("<i",data[:4])[0]#endianness may affecting data transfer filenamebytes = struct.unpack("<i",data[4:])[0] data = socket.recv(1024) filename = data[:filenamebytes] curkb = 1 print 'getting '+filename+"..." writeto = open('./footage/'+filename,'wb') while curkb <= filekb: print '\r' + str(curkb) + "/" + str(filekb), sys.stdout.flush() writeto.write(data) data = socket.recv(1024) curkb += 1 writeto.close() print 'download of '+filename+' successful.' else: print 'download failed.'
i solved problem myself advice jasonharper.
by switching out code measuring in kb more normal code worked in bytes, data socket read. i'm not sure whether original cause of fault down floating point issue or other reason, worked. if need more capacity i'll switch using longs.
for sake of code readability , decrease chance of rounding errors, stopped filename , data being lumped single transmission block.
the original code overengineered when simpler code have done trick.
revised code:
client
def receivedownload(socket): #gets header data = socket.recv(8) if data != 'abort': fileb = struct.unpack("<i",data[:4])[0]#endianness may affecting data transfer filenamebytes = struct.unpack("<i",data[4:])[0] data = socket.recv(filenamebytes) filename = data curb = 0 print 'getting '+filename+"..." writeto = open('./footage/'+filename,'wb') while curb < fileb: sys.stdout.flush() data = socket.recv(1024) writeto.write(data) curb += len(data) print '\r' + str(curb) + "/" + str(fileb), writeto.close() print 'download of '+filename+' successful.' else: print 'download failed.'
server
def senddata(filename,socket): try: filehandle = open(filename,'rb') except ioerror: socket.sendall('abort') print 'file ' +filename+ ' not found; not sending...' else: #writes 8 byte header consisting of: #length of file in kb (4b) #length of filename (4b) numbytes = struct.pack("<i",math.ceil(os.stat(filename).st_size)) #amount of kb (1024) receive, written 4-byte integer filenamebytes = struct.pack("<i",len(filename)) print 'sending '+filename+'...' socket.sendall(numbytes + filenamebytes) data = filename socket.sendall(data) while true: data = filehandle.read(1024) socket.sendall(data) if not data: break filehandle.close() print 'send complete.'
Comments
Post a Comment