我无法更新HTTP2实施流量控制窗口,所以客户端无法发送的数据的其余部分

问题描述 投票:3回答:1

我在执行简单ASYNCIO HTTP2服务器和客户端在Python 3.6。它要求实行流量控制。我已经流控制窗口设置为与功能self.outbound_flow_control_window = 2048客户端2048个字节,之后客户端发送数据的2048字节块,服务器不处理和确认所接收到的数据,从而客户机可以发送2048另一块字节

我已经尝试这些功能,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)

从客户端接收数据(2048个字节)后,我想服务器承认并更新客户端,它现在可以发送更多的数据,但flow_control_windows客户端甚至接收窗口更新帧之后依然为0,

python-asyncio http2 flow-control hyper
1个回答
2
投票

你有没有流量控制工作示例服务器?如果没有这样做。

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

你是混合手动和自动流程控制。这里重读自动流量控制部分,并使用自动控制。

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

这种自动战略是围绕一个单一的方法构建的:acknowledge_received_data。这种方法标志,以您的应用程序已经处理了一定数量的流量控制字节,这个窗口应该以某种方式递增的连接对象。每当你的应用程序“处理”一些接收的字节数,这个方法应该叫表明它们已被处理。

这种方法和increment_flow_control_window之间的主要区别是,该方法acknowledge_received_data不保证它会发出WINDOW_UPDATE帧,并且如果这样做,将不一定发射它们仅用于流或只有帧。相反,WINDOW_UPDATE帧将被合并:只有当字节一定数量的已经释放了他们将被发射。

现在来看看它采用流量控制古玩例子。如果您是从服务器接收窗口更新事件可能是你不处理流ID 0正常。

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

具体地,发送数据功能:

 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())

如果你想发送4K字节的等待时间流控制窗口,发送您的2K字节,则流量控制窗口再次等待。

如果您收到的窗口更新你应该有这样的代码

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
© www.soinside.com 2019 - 2024. All rights reserved.