febeks17 febeks17 - 1 month ago 10
Python Question

Sending file over UDP divided into fragments

I have been dealing with sending file which is divided into fragments set by user on input. Problem is, I am getting error:

rec_list[fragIndex - 1] = data

IndexError: list assignment index out of range


I am also sending single string messages like in a chat and it works normally.
I can't find a bug in my code but maybe you can.

Btw, there are variables which might help with math which doesn't fit probably.

fragSize = 3


fragIndex = 216


fragCount = 215


Problem is, total number of fragments should be 215 (precalculated before sending - IS OK),
index
shouldn't be more than
count
! That is the problem. And it doesn't happen with strings. Only here with file.

Sending:

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: '))


And here is sending function for files:

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:]


Receiving:

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


This is only if I want to receive message of type file: (because it is divided into more message types)

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

Answer

You tried to compare apples to oranges. Well, bytes to str but wikipedia doesn't say anything about that.

while contents!='':
    ...

contents is a bytes object and '' is a str object. In python 3, those two things can never be equal. Firing up the shell we see that

>>> 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!

Since all objects have a truthiness (that is, bool(some_object) is meaningful) and bytes objects turn False when they are empty, you can just do

while contents:
    ....
Comments