Compartir a través de


Opciones de configuración de QUIC

La System.Net.Quic biblioteca usa clases de opciones para configurar los objetos de protocolo (QuicListener y QuicConnection) antes de su construcción e inicialización. Hay tres clases de opciones diferentes para hacerlo:

Todas las clases de opciones se pueden configurar de forma incremental, lo que significa que no requieren que ninguna de sus propiedades se inicialice a través del constructor y se pueda configurar de forma independiente. En el momento en que se utilizan para configurar un nuevo listener o una conexión, las opciones se validan y se arroja un tipo apropiado de ArgumentException para cualquier valor obligatorio faltante o mal configurado. Por ejemplo, si no se establece obligatorio QuicConnectionOptions.DefaultStreamErrorCode , la llamada a ConnectAsync(QuicClientConnectionOptions, CancellationToken) produce ArgumentOutOfRangeException.

QuicListenerOptions

QuicListenerOptions se usa en QuicListener.ListenAsync(QuicListenerOptions, CancellationToken) al iniciar un nuevo QuicListener. Las propiedades de configuración individuales son:

Protocolos de Aplicación

ApplicationProtocols defina los protocolos de aplicación aceptados por el servidor (RFC 7301 - ALPN). Puede contener varios valores para distintos protocolos que no pueden estar relacionados. En el proceso de aceptar una nueva conexión, el agente de escucha puede restringir o seleccionar un protocolo específico para cada conexión entrante, consulte QuicListenerOptions.ConnectionOptionsCallback. Esta propiedad es obligatoria y debe contener al menos un valor.

ConnectionOptionsCallback

ConnectionOptionsCallback es un delegado para elegir QuicServerConnectionOptions en una conexión entrante. La función recibe una instancia inicializada parcialmente de QuicConnection y SslClientHelloInfo contiene el nombre del servidor solicitado por el cliente (RFC 6066 - SNI). El delegado se invoca para cada conexión entrante. Puede devolver diferentes opciones en función de la información de cliente proporcionada o puede devolver de forma segura la misma instancia de las opciones cada vez. El propósito y la forma del delegado son intencionadamente similares a ServerOptionsSelectionCallback usado en SslStream.AuthenticateAsServerAsync(ServerOptionsSelectionCallback, Object, CancellationToken). Esta propiedad es obligatoria.

ListenBacklog

ListenBacklog determina el número de conexiones entrantes que el agente de escucha puede mantener antes de que se rechacen otras adicionales. Cada intento de establecer una conexión cuenta, incluso cuando falla o cuando la conexión se interrumpe mientras se espera en la cola. Los procesos en curso para establecer una nueva conexión también cuentan para este límite. Las conexiones o los intentos de conexión se cuentan hasta que se recuperan a través de QuicListener.AcceptConnectionAsync(CancellationToken). El propósito del límite de trabajos pendientes es evitar que los servidores se agoten por más conexiones entrantes de las que pueden procesar. Esta propiedad es opcional, el valor predeterminado es 512.

ListenEndPoint

ListenEndPoint contiene la dirección IP y el puerto en el que la escucha aceptará nuevas conexiones. Debido a la implementación subyacente, MsQuic el agente de escucha siempre se enlaza a un socket comodín de pila dual, independientemente de lo que se especifique aquí. Esto puede provocar algunos comportamientos inesperados, especialmente en comparación con los sockets TCP normales, como en los casos HTTP/1.1 y HTTP/2. Para obtener más información, vea Guía de solución de problemas de QUIC. Esta propiedad es obligatoria.

QuicConnectionOptions

QuicConnectionOptions las opciones se comparten entre QuicClientConnectionOptions y QuicServerConnectionOptions. Es una clase base abstracta y no se puede usar por sí misma. Contiene estas propiedades:

DefaultCloseErrorCode

DefaultCloseErrorCode se usa cuando la conexión se elimina sin llamar a QuicConnection.CloseAsync(Int64, CancellationToken). Es necesario que el protocolo QUIC proporcione un motivo de nivel de aplicación para cerrar una conexión (RFC 9000 - Cierre de conexión). QuicConnection no tiene forma de forzar que el código de aplicación llame CloseAsync(Int64, CancellationToken) antes de eliminar la conexión. En tal caso, la conexión debe saber qué código de error se va a usar. Esta propiedad es obligatoria.

DefaultStreamErrorCode

DefaultStreamErrorCode se usa cuando se elimina una secuencia antes de leer todos los datos. Al recibir datos a través del flujo QUIC, una aplicación puede consumir todos los datos o, si no, debe abortar su lado de lectura. De forma similar al cierre de la conexión, el protocolo QUIC requiere un motivo de nivel de aplicación para anular el lado de lectura (RFC 9000 - Detener el envío). Esta propiedad es obligatoria.

HandshakeTimeout

HandshakeTimeout establece el límite de tiempo en el que se debe establecer completamente la conexión; de lo contrario, se anula. Es posible establecer este valor en InfiniteTimeSpan , pero no se recomienda. Los intentos de conexión pueden bloquearse indefinidamente y no hay ningún medio para borrarlos aparte de detener el QuicListener. Esta propiedad es opcional, el valor predeterminado es de 10 segundos.

TiempoDeInactividad

Si la conexión está inactiva durante más tiempo que el especificado IdleTimeout, se desconecta. Esta opción forma parte de la especificación del protocolo QUIC (RFC 9000 - Tiempo de espera de inactividad) y se envía al par durante el apretón de manos de la conexión. A continuación, la conexión toma el menor entre su propio valor y el tiempo de espera de inactividad del par y lo utiliza. Por lo tanto, la conexión puede cerrarse en el tiempo de espera de inactividad antes del tiempo configurado en esta opción. Esta propiedad es opcional, el valor predeterminado se basa en MsQuic, que es de 30 segundos.

InitialReceiveWindowSizes

InitialReceiveWindowSizes especifica un conjunto de valores que, inicialmente, limita la cantidad de datos que se pueden recibir mediante la conexión o el flujo. El protocolo QUIC define un mecanismo para limitar la cantidad de datos que se pueden enviar a través de las secuencias individuales, así como de forma acumulativa para toda la conexión (RFC 9000 - Control de flujo de datos). Estos límites solo se aplican antes de que la aplicación empiece a consumir los datos. Después, MsQuic ajusta continuamente el tamaño de la ventana de recepción en función de la rapidez con la que la aplicación las lee. Esta propiedad es de QuicReceiveWindowSizes tipo , que contiene estas opciones:

Estos valores deben ser un entero no negativo que sea una potencia de 2; se trata de una limitación heredada de MsQuic. Si se establece cualquiera de estos valores en 0, básicamente, no se recibirá ningún dato por la secuencia específica o una conexión en su conjunto. Esta propiedad es opcional, los valores predeterminados son de 64 KB para una secuencia y 64 MB para una conexión.

KeepAliveInterval

KeepAliveInterval determina si y con qué frecuencia se envían fotogramas PING para mantener la conexión activa y evitar que se cierre IdleTimeout (RFC 9000 - Fotogramas PING). Si establece esta propiedad, considere la recomendación de RFC 9000: aplazar el tiempo de espera de inactividad. Establecer el valor demasiado bajo podría afectar negativamente al rendimiento. Además, establecer la propiedad demasiado cerca del tiempo de espera de inactividad podría provocar cierres de conexión. Esta propiedad es opcional, el valor predeterminado significa InfiniteTimeSpan que no se enviará ningún PING.

MaxInboundBidirectionalStreams

MaxInboundBidirectionalStreams determina el número máximo de secuencias bidireccionales simultáneamente activas que la conexión está dispuesta a aceptar. Tenga en cuenta que esto difiere de la forma en que la especificación QUIC define la simultaneidad de control (RFC 9000 - Controlar la simultaneidad). El protocolo QUIC cuenta los flujos acumulativamente, durante la duración de la conexión y usa un límite cada vez mayor para determinar el número total de secuencias aceptadas por la conexión, incluidas las secuencias ya cerradas (RFC 9000 - MAX_STREAMS Frames). Esta propiedad simplifica esto para que la aplicación solo especifique el límite de flujo simultáneo y MsQuic se encarga de traducir este límite a los fotogramas correspondientes MAX_STREAMS . Esta propiedad es opcional, el valor predeterminado es 0 para las conexiones de cliente y 100 para las conexiones de servidor.

MaxInboundUnidirectionalStreams

MaxInboundUnidirectionalStreams determina el número máximo de secuencias unidireccionales simultáneamente activas que la conexión está dispuesta a aceptar. Tenga en cuenta que esto difiere de la forma en que la especificación QUIC define el control de la simultaneidad de flujos (RFC 9000 - Control de simultaneidad). El protocolo QUIC cuenta los flujos acumulativamente, durante la duración de la conexión y usa un límite cada vez mayor para determinar el número total de secuencias aceptadas por la conexión, incluidas las secuencias ya cerradas (RFC 9000 - MAX_STREAMS Frames). Esta propiedad simplifica esto para que la aplicación solo especifique el límite de flujo simultáneo y MsQuic se encarga de traducir este límite a los fotogramas correspondientes MAX_STREAMS . Esta propiedad es opcional, el valor predeterminado es 0 para las conexiones de cliente y 10 para las conexiones de servidor.

StreamCapacityCallback

StreamCapacityCallback es una devolución de llamada que se invoca cada vez que el par libera una nueva capacidad de secuencia a través de MAX_STREAMS y, como resultado, la capacidad actual está por encima de 0. Los valores proporcionados en los argumentos de devolución de llamada son incrementos de capacidad, lo que significa que la suma de todos los valores de la devolución de llamada será igual al último valor recibido de MAX_STREAMS (RFC 9000 - MAX_STREAMS Frames). Esta devolución de llamada se diseñó para admitir la funcionalidad de SocketsHttpHandler.EnableMultipleHttp3Connections y viene con varias advertencias:

El siguiente escenario simplificado captura el comportamiento de la apertura de una secuencia y de la función de devolución de llamada.

  1. El cliente inicia la conexión al servidor a través de:

    var client = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions
    {
        ...
        StreamCapacityCallback = (connection, args) =>
            Console.WriteLine($"{connection} stream capacity increased by: unidi += {args.UnidirectionalIncrement}, bidi += {args.BidirectionalIncrement}")
    };
    
  2. El servidor envía la configuración inicial al cliente con el límite 2 de flujos para secuencias unidireccionales y 0 para bidireccionales.

  3. Se invoca al objeto del cliente StreamCapacityCallback y este imprime:

    [conn][0x58575BF805B0] stream capacity increased by: unidi += 2, bidi += 0
    
  4. La llamada del cliente a ConnectAsync se completa con la conexión [conn][0x58575BF805B0].

  5. El cliente intenta abrir algunos flujos:

    var stream1 = await connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional);
    var stream2 = await connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional);
    // The following call will get suspended because the stream's limit has been reached.
    var taskStream3 = connection.OpenOutboundStreamAsync(QuicStreamType.Unidirectional);
    
  6. El cliente finaliza y cierra las dos primeras secuencias:

    await stream1.WriteAsync(data, completeWrites: true);
    await stream1.DisposeAsync();
    await stream2.WriteAsync(data, completeWrites: true);
    await stream2.DisposeAsync();
    Console.WriteLine($"Stream 3 {(taskStream3.IsCompleted ? "opened" : "pending")}");
    
  7. El cliente imprime:

    Stream 3 pending
    
  8. El servidor libera capacidad adicional de 2 después de procesar las dos primeras secuencias.

  9. Suceden dos cosas en el cliente. En primer lugar, se abre una tercera secuencia:

    var stream3 = await taskStream3;
    

    A continuación, se vuelve a llamar al cliente StreamCapacityCallback y este imprime:

    [conn][0x58575BF805B0] stream capacity increased by: unidi += 2, bidi += 0
    

Esta propiedad es opcional.

QuicServerConnectionOptions

QuicServerConnectionOptions las opciones son específicas para una conexión del lado servidor. Aparte de las propiedades heredadas de QuicConnectionOptions, contiene lo siguiente:

OpcionesDeAutenticaciónDelServidor

ServerAuthenticationOptions contiene la configuración de TLS para la conexión del servidor. Las opciones son las mismas que se usan en SslStream.AuthenticateAsServer(SslServerAuthenticationOptions) y SslStream.AuthenticateAsServerAsync(SslServerAuthenticationOptions, CancellationToken). Para el servidor QUIC, SslServerAuthenticationOptions es válido si:

Esta propiedad es obligatoria y debe cumplir las condiciones enumeradas.

QuicClientConnectionOptions

QuicClientConnectionOptions las opciones son específicas de una conexión del lado cliente. Aparte de las propiedades heredadas de QuicConnectionOptions, contiene lo siguiente:

ClientAuthenticationOptions

ClientAuthenticationOptions contiene la configuración de TLS para la conexión de cliente. Las opciones son las mismas que se usan en SslStream.AuthenticateAsClient(SslClientAuthenticationOptions) y SslStream.AuthenticateAsClientAsync(SslClientAuthenticationOptions, CancellationToken). Para el cliente QUIC, SslClientAuthenticationOptions es válido si:

Esta propiedad es obligatoria y debe cumplir las condiciones enumeradas.

LocalEndPoint

LocalEndPoint contiene la dirección IP y el puerto al que se enlazará la conexión de cliente. Si no se especifica, el sistema operativo asigna una dirección IP y un puerto. Esta propiedad es opcional.

Punto Final Remoto

RemoteEndPoint puede ser DnsEndPoint o IPEndPoint del par con el que se establece la conexión. Si es un DnsEndPoint, se usa la primera dirección IP devuelta por Dns.GetHostAddressesAsync(String, CancellationToken). Esta propiedad es obligatoria.