简体   繁体   中英

I am unable to update Flow control window in HTTP2 implementation, so the client is unable to send the rest of the data

I am implementing simple asyncio HTTP2 server and client in Python 3.6. It requires to implement Flow control. I have set the flow control window to 2048 bytes on client side with function self.outbound_flow_control_window=2048, after the clients send a 2048 byte chunk of data, server is not processing and acknowledging the received data so the client can send another chunk of 2048 bytes

i have already tried these functions, self.conn.acknowledge_received_data(2048, event.stream_id) self.conn.increment_flow_control_window(2048, event.stream_id)

elif isinstance(event, DataReceived):
    self.receive_data(event.data, event.stream_id)
    self.conn.acknowledge_received_data(2048, event.stream_id)
    self.conn.increment_flow_control_window(2048, event.stream_id)

After receiving data (2048 bytes) from client, i want the server to acknowledge and update the client that it can send more data now, but flow_control_windows on client remains 0, even after receiving window update frames

Do you have the example server without flow control working? If not do so.

https://github.com/python-hyper/hyper-h2/blob/master/examples/asyncio/asyncio-server.py

You are mixing manual and automatic flow control. Reread the automatic flow control section here and use the automatic control.

https://python-hyper.org/projects/h2/en/stable/advanced-usage.html

This automatic strategy is built around a single method: acknowledge_received_data. This method flags to the connection object that your application has dealt with a certain number of flow controlled bytes, and that the window should be incremented in some way. Whenever your application has “processed” some received bytes, this method should be called to signal that they have been processed.

The key difference between this method and increment_flow_control_window is that the method acknowledge_received_data does not guarantee that it will emit a WINDOW_UPDATE frame, and if it does it will not necessarily emit them for only the stream or only the frame. Instead, the WINDOW_UPDATE frames will be coalesced: they will be emitted only when a certain number of bytes have been freed up.

Now look at the curio example which uses flow control. If you are receiving the window update events from the server likely you are not handling stream id 0 properly.

https://github.com/python-hyper/hyper-h2/blob/master/examples/curio/curio-server.py

Specifically the send data function:

 while True:
        while not self.conn.local_flow_control_window(stream_id):
            await self.wait_for_flow_control(stream_id)

        chunk_size = min(
            self.conn.local_flow_control_window(stream_id),
            READ_CHUNK_SIZE,
        )

        data = fileobj.read(chunk_size)
        keep_reading = (len(data) == chunk_size)

        self.conn.send_data(stream_id, data, not keep_reading)
        await self.sock.sendall(self.conn.data_to_send())

If you want to send 4k bytes you wait on the flow control window, send your 2k bytes then wait again on the flow control window.

If you are receiving the window update you should have code like this

async def window_updated(self, event):
    """
    Unblock streams waiting on flow control, if needed.
    """
    stream_id = event.stream_id

    if stream_id and stream_id in self.flow_control_events:
        evt = self.flow_control_events.pop(stream_id)
        await evt.set()
    elif not stream_id:
        # Need to keep a real list here to use only the events present at
        # this time.
        blocked_streams = list(self.flow_control_events.keys())
        for stream_id in blocked_streams:
            event = self.flow_control_events.pop(stream_id)
            await event.set()
    return

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM