通过UDP发送文件分为多个片段

时间:2016-10-30 02:49:04

标签: python file sockets udp

我一直在处理发送文件,该文件被分成用户在输入时设置的片段。问题是,我收到错误:

rec_list[fragIndex - 1] = data IndexError: list assignment index out of range

我也在发送单个字符串消息,就像在聊天中一样,它正常工作。 我在代码中找不到错误,但也许你可以。

顺便说一下,有些变量可能对数学有帮助,但可能不适合。

fragSize = 3

fragIndex = 216

fragCount = 215

问题是,片段的总数应该是215(在发送之前预先计算 - 可以),index不应超过count!那就是问题所在。字符串不会发生这种情况。只有这里有文件。

发送:

fragSize = int(input('Fragment size: ')) #max size of fragment
        while True:
            message = input('Enter message: ')
            fragIndex=0 #reset fragment indexing

    #asking for fragment size
            if(message[:3] == '-sf'):
                fragSize = int(input('Fragment size: '))

这里是发送文件的功能:

if (message[:2] == '-f'):
                mType = 3
                if message.startswith('-f'):
                   message = message[3:]

                file_name = message
                f=open(file_name,"rb")
                contents = f.read()
                fragCount = math.ceil(len(contents) / fragSize)

                while contents!= '':
                    data = bytearray()
                    data.extend(contents[:fragSize])
                    fragIndex += 1
                    crc = crc32(data)
                    header = struct.pack('!hIIII', mType, fragSize, fragIndex, fragCount, crc)
                    self.sock.sendto(header + bytearray(data), (self.host, self.port))
                    contents = contents[fragSize:]

接收:

while True:
            received_chunks = 0
            rec_list = []
            while True:
                data, addr = sock.recvfrom(65535)
                header = data[:18]
                data = data[18:]
                (mType, fragSize, fragIndex, fragCount, crc) = struct.unpack('!hIIII', header)

                print(
                '\nTyp: ' + str(mType) +
                '\nFragSize: ' + str(fragSize) +
                '\nFragIndex: ' + str(fragIndex) +
                '\nFragCount: ' + str(fragCount) +
                '\nCRC: ' + str(crc)
                )

                if len(rec_list) < fragCount:
                    need_to_add = fragCount - len(rec_list)
                    rec_list.extend([''] * need_to_add)  # empty list for messages of size fragCount
                rec_list[fragIndex - 1] = data

                received_chunks += 1
                if received_chunks == fragCount:
                    break  # This is where the second while loop ends

仅当我想接收文件类型的消息时:(因为它被分成更多的消息类型)

if mType == 3:
     content = b''.join(rec_list)
     f = open('filename.py','wb')
     f.write(content)

1 个答案:

答案 0 :(得分:1)

您尝试比较apples to oranges。好吧,bytesstr但是维基百科没有说明这一点。

while contents!='':
    ...

contentsbytes个对象,''str个对象。在python 3中,这两件事永远不会是平等的。解雇shell我们看到了

>>> b''==''
False
>>> 
>>> contents = b"I am the very model"
>>> while contents != '':
...     if not contents:
...         print("The while didn't catch it!")
...         break
...     contents = contents[3:]
... 
The while didn't catch it!

由于所有对象都具有真实性(即bool(some_object)有意义),而bytes对象在空时转为False,您可以这样做

while contents:
    ....

更新

不是原始答案的一部分,但提出了一个关于将重试发送回客户端的问题。服务器端在这里草拟

while True:
            received_chunks = 0
            fragCount = -1
            rec_list = []
            while True:
                # wait forever for next conversation
                if fragCount == -1:
                    sock.settimeout(None)
                try:
                    data, addr = sock.recvfrom(65535)
                except socket.timeout:
                    # scan for blank slots in rec_list
                    retries = [i for i, data in rec_list if not data]
                    # packet is mType, numFrags, FragList
                    # TODO: I just invented 13 for retry mtype
                    sock.sendto(struct.pack("!{}h".format(len(retries+2)), 13,
                        len(retries), *retries)
                    continue
                # our first packet, set timeout for retries
                if fragCount == -1:
                    sock.settimeout(2)
                header = data[:18]
                data = data[18:]
                (mType, fragSize, fragIndex, fragCount, crc) = struct.unpack('!hIIII', header)

                print(
                '\nTyp: ' + str(mType) +
                '\nFragSize: ' + str(fragSize) +
                '\nFragIndex: ' + str(fragIndex) +
                '\nFragCount: ' + str(fragCount) +
                '\nCRC: ' + str(crc)
                )

                if len(rec_list) < fragCount:
                    need_to_add = fragCount - len(rec_list)
                    rec_list.extend([''] * need_to_add)  # empty list for messages of size fragCount
                rec_list[fragIndex - 1] = data

                received_chunks += 1
                if received_chunks == fragCount:
                    break  # This is where the second while loop ends