python - 通过Python套接字发送文件-卡在socket.sendall

标签 python python-2.7 file sockets

我写了我认为相当简单的脚本,可以使用Python套接字通过网络下载文件,但是服务器卡在服务器端的socket.sendall上。我可以获得一次我想要的文件,但是随后对senddata的调用导致崩溃。

在进一步研究之后,我相当确定这与打包 header 数据有关,这意味着它很可能是一个低级问题,超出了我的范围。

对于上下文:“主”代码在x86计算机上运行,​​而“从”代码在Raspberry Pi Zero(ARM)上运行。

header 已在代码中定义,但这是一个概述:

  • 文件长度和文件名长度 bundle 在两个uint的8字节标题中。
  • 文件名和(h264视频)数据的第一块 bundle 在一起,形成1kb的初始发送。
  • 然后,服务器将以1kb的块发送更多数据,直到发送完整个文件为止。

  • 我对为什么这不起作用感到困惑,因为这看起来像是例行代码。

    从站(服务器)
    #takes filename and sends the data to the 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) to receive, written to 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.'
    

    硕士(客户)
    def ReceiveDownload(socket):
        #gets header
        data = socket.recv(8)
        if data != 'ABORT':
            filekb = struct.unpack("<I",data[:4])[0]#endianness may be 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.'
    

    最佳答案

    我自己根据jasonharper的建议解决了这个问题。

    通过使用以字节为单位的更普通的代码切换出以kb为单位的代码,总是读取套接字中的所有数据。我不确定此故障的最初原因是否是浮点问题或其他原因,但它确实有效。如果我需要更多容量,我将改用Longs。

    为了便于阅读代码并减少舍入错误的可能性,我还停止了将文件名和数据集中在一起的情况,将其合并到一个传输块中。

    当更简单的代码可以解决问题时,原始代码将被过度设计。

    修改后的代码:

    客户

    def ReceiveDownload(socket):
        #gets header
        data = socket.recv(8)
        if data != 'ABORT':
            fileb = struct.unpack("<I",data[:4])[0]#endianness may be 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.'
    

    服务器
    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) to receive, written to 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.'
    

    关于python - 通过Python套接字发送文件-卡在socket.sendall,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45680693/

    相关文章:

    python - pandas.concat 仅使用一张表中的索引

    python - 如何仅替换文件中的某些单词

    python - wx.CheckListBox 的设置工作不符合预期

    java - 文件删除和重命名问题

    c# - 该进程无法访问文件\App_Data\ASPNETDB.MDF',因为它正在被另一个进程使用。

    file - 组织大量文件上传

    python - API 一段时间后停止工作

    python - 如何将颜色条添加到 kdeplot

    python - 通过不同的execute_script调用创建和访问js变量

    python - python 中的依赖注入(inject)(取决于模块可用性)