用Python生成QUIC通信量,低吞吐量

用Python生成QUIC通信量,低吞吐量,python,asynchronous,quic,Python,Asynchronous,Quic,我正在编写一个简单的速度测试程序,可以测量两台设备之间的quic吞吐量。 有一个python脚本可以启动客户端或服务器端。客户端生成流量,服务器测量它接收的流量。就这么简单。但不知何故,即使我在同一台机器上同时运行服务器和客户端,它的速度上限约为115MB/s。在同一台机器上,当我生成TCP或UDP流量时,其速度大约为30 Gb/s,因此带宽不是问题。我使用的库是aioquic,不幸的是它几乎没有文档记录。问题是如何提高吞吐量?我主要担心的是这里的一些代码。看起来transmit()是一个阻塞函

我正在编写一个简单的速度测试程序,可以测量两台设备之间的quic吞吐量。 有一个python脚本可以启动客户端或服务器端。客户端生成流量,服务器测量它接收的流量。就这么简单。但不知何故,即使我在同一台机器上同时运行服务器和客户端,它的速度上限约为115MB/s。在同一台机器上,当我生成TCP或UDP流量时,其速度大约为30 Gb/s,因此带宽不是问题。我使用的库是aioquic,不幸的是它几乎没有文档记录。问题是如何提高吞吐量?我主要担心的是这里的一些代码。看起来transmit()是一个阻塞函数,但当我没有暂停/继续机制或某种粗糙的sleep()时,程序就会挂起,甚至产生低流量

from connector import * #my base class
import asyncio as asc
import aioquic.asyncio
from aioquic.quic.configuration import QuicConfiguration
import ssl

class QUIC_client(client):
    def __init__(self, host, port, use_json):
        super().__init__(host, port, use_json)
        self.traffic_type = 'quic'
        self.payload = b'p'*(self.quic_payload_size-1)+b'\n'

        self.config = QuicConfiguration(
            is_client = True,
            verify_mode = ssl.CERT_NONE
            )

    async def _maintask(self, time):
        self._infomessage(f'connecting to server {self.host}:{self.port}')
        async with aioquic.asyncio.connect(host=self.host, port=self.port, configuration=self.config) as client:
            await client.wait_connected()
            self._infomessage(message=f'connection successful')
            reader, writer = await client.create_stream()
            self._infomessage(message=f'stream created, now transmitting')

            timetofinish = millis() + (time*1000)
            while(millis() < timetofinish):
                for i in range(300):
                    writer.write(self.payload)
                writer.write(b'PAUSE\n')
                client.transmit()
                #HERE
                #when i just send data over and over again program hangs on client side
                #thats why i send 'PAUSE' and wait for 'CONTINUE'
                #its just a temporary solution but i couldnt find anything to just wait until send is complete
                line = await reader.readline()
                if line == b'CONTINUE\n':
                    #self._infomessage(message=f'continuing...')
                    pass
                else:
                    self._infomessage(message=f'connection closed')
                    break

            writer.write(b'STOP\n')
            client.transmit()
            client.close()
            await client.wait_closed()
            self._infomessage(message=f'client finished')

    def run_test(self, time):
        super().run_test(time)
        loop = asc.get_event_loop()
        loop.run_until_complete(self._maintask(time))



class QUIC_server(server):
    def __init__(self, port, interval, use_json):
        super().__init__(port, interval, use_json)
        self.traffic_type = 'quic'
        self.config = QuicConfiguration(
            is_client = False
            )
        self.config.load_cert_chain('cert.pem', 'key.pem')
        self.loop = asc.get_event_loop()

    def _streamhandler(self, reader, writer):
        self._infomessage(message='stream created')
        self.currentstreamtask = self.loop.create_task(self._currentstreamhandler(reader, writer))

    async def _currentstreamhandler(self, reader, writer):
        data_counter = 0
        timer = millis()
        while(True):
            line = await reader.readline()
            if line == b'':
                self._infomessage(message='connection interrupted! now exitting', is_error=True)
                return
            elif line == b'STOP\n':
                self._infomessage('server finished')
                self.loop.stop()
                return
            elif line == b'PAUSE\n':
                    writer.write(b'CONTINUE\n')
                    #TODO find a better way to control data flow
            else:
                data_counter += 1
                if (millis() - timer) > (self.interval*1000):
                    timer = millis()
                    self._datamessage(bps_value=(data_counter*self.quic_payload_size*8/self.interval))
                    data_counter = 0

    def listen(self):
        super().listen()
        try:
            self.server_task = self.loop.create_task(
                aioquic.asyncio.serve(host='0.0.0.0',
                port=self.port,
                configuration=self.config,
                stream_handler=self._streamhandler
                ))
            self.loop.run_forever()
        except asc.CancelledError:
            print('cancelled error')

#basically when running a test
#QUIC_client or QUIC_server instance is created
#and then run_test() or listen() is called

从连接器导入*#我的基类
将异步IO作为asc导入
导入aioquic.asyncio
从aioquic.quic.configuration导入QuicConfiguration
导入ssl
类QUIC_客户机(客户机):
def _uinit _;(self、host、port、use_json):
super()
self.traffic_type='quic'
self.payload=b'p'*(self.quic_payload_size-1)+b'\n'
self.config=QuicConfiguration(
_client=True,
验证\u mode=ssl.CERT\u无
)
异步定义主任务(自身、时间):
self._infomessage(f'连接到服务器{self.host}:{self.port}')
使用aioquic.asyncio.connect(host=self.host,port=self.port,configuration=self.config)作为客户端进行异步:
等待客户端。等待连接()
self.\u infomessage(message=f'connection successful')
reader,writer=wait client.create_stream()
self.\u infomessage(message=f‘已创建流,正在传输’)
timetofinish=millis()+(时间*1000)
而(毫秒()(自间隔*1000):
计时器=毫秒()
self.\u数据消息(bps\u值=(数据计数器*self.quic\u有效负载*8/self.interval))
数据计数器=0
def监听(self):
超级听
尝试:
self.server\u task=self.loop.create\u task(
aioquic.asyncio.service(host='0.0.0.0',
端口=self.port,
配置=self.config,
stream\u handler=self.\u streamhandler
))
self.loop.run_forever()
除asc.Cancelled错误外:
打印('取消错误')
#基本上是在运行测试时
#创建QUIC_客户端或QUIC_服务器实例
#然后调用run_test()或listen()

您可以尝试通常比标准asyncio实现快得多的方法(但不确定是否与aioquic兼容)。此外,您可能希望避免读线速度较慢,并以相当大的数据块(至少64KB)发送数据以避免Python速度较慢。不幸的是,当我增加有效负载时,它不起作用:如果我增加循环范围(现在为300),它不会改变任何东西。若我增加有效负载大小(现在是65500,低于udp数据字段大小),程序也会冻结,不,不幸的是,这个库与uvloop不兼容。您是否认为这可能与效率无关,而是我做错了什么?冻结可能是由于此处解释的死锁情况造成的(TLDR:客户端或服务器需要同时发送和接收;如果发送和接收两者交替,则可能会发生死锁)关于您获得的速度:很难说在使用框架时这是否正常。例如,加密成本是多少,是否