Description
I'm typically sending small messages, but in some instances a large amount of data has to be sent over the socket.
For this, to get around the maximum packet size, I chunked up the input bytes into chunks from the sender side, and stitch then up again on the receiver side.
For small amount of chunks (~10-ish), this works fine and without any problems.
For a large amount of chunks (>40), the receiver starts losing packets.
Below the client-side code, create_chunks creates json objects which contain the data, the total amount of chunks in this initial packet, and the chunk_id, so I know which packets I have received.
def put(self, packet: Packet):
data = packet.to_pickle()
import time
for chunk in create_chunks(data):
print("Emitting packet with id", chunk["chunk_id"], len(pickle.dumps(chunk)))
self.client.emit("io", pickle.dumps(chunk))
Server side code waits for data and stitches together.
@self.sio.on("io")
def io(data):
self._intermediate_data_buffer.append(pickle.loads(data))
logging.info(f'Receiving packet with id {self._intermediate_data_buffer[-1]["chunk_id"]}')
n_chunks = self._intermediate_data_buffer[0].get("length")
if n_chunks == len(self._intermediate_data_buffer):
recreated_data = b''.join(
x.get("data") for x in sorted(self._intermediate_data_buffer, key=lambda d: d.get("chunk_id"))
)
pkt = Packet.from_pickle(recreated_data)
self._intermediate_data_buffer.clear()
if self._on_packet_callback is not None:
self._on_packet_callback(pkt)
else:
self.queue.put(pkt)
Logs from client side:
Emitting packet with id 0 524351
Emitting packet with id 1 524351
...
Emitting packet with id 265 524352
Emitting packet with id 266 219229
Logs on server side:
2024-05-01 19:09:43,249 [INFO] Receiving packet with id 0
2024-05-01 19:09:43,249 [INFO] Receiving packet with id 1
...
2024-05-01 19:09:43,260 [INFO] Receiving packet with id 38
2024-05-01 19:09:43,260 [INFO] Receiving packet with id 39
I can 'get around' this problem by adding a time.sleep(0.2) inbetween packet sending on the client side. Ideally I do not delay the sending of packets unnecessarily. Though this does indicate the problem has to do with some kind of internal buffer filling up.
The only thing I found on the flask-socketio documentation regarding message size regards a single message's size, and not the total aggregated size of all messages in the buffer.
max_http_buffer_size – The maximum size of a message when using the polling transport. The default is 1,000,000 bytes.