QUIC 구성 옵션
System.Net.Quic 라이브러리는 옵션 클래스를 사용하여 생성 및 초기화 전에 프로토콜 개체(QuicListener 및 QuicConnection)를 구성합니다. 이렇게 하려면 세 가지 옵션 클래스가 있습니다.
- QuicListenerOptions: QuicListener.ListenAsync(QuicListenerOptions, CancellationToken)를 시작하기 전에 QuicListener을 구성합니다.
- QuicClientConnectionOptions: QuicConnection.ConnectAsync(QuicClientConnectionOptions, CancellationToken)를 통해 설정하기 전에 나가는 QuicConnection을 구성하다
- QuicServerConnectionOptions: QuicListener.AcceptConnectionAsync(CancellationToken)로 전달되기 전에 들어오는 QuicConnection을 구성합니다.
모든 옵션 클래스를 증분 방식으로 설정할 수 있습니다. 즉, 생성자를 통해 속성을 초기화할 필요가 없으며 독립적으로 설정할 수 있습니다. 그러나 새 수신기나 연결을 구성하기 위해 사용되는 순간, 옵션의 유효성이 검사되며 필수 값이 누락되었거나 값이 잘못 구성된 경우에 적절한 유형의 ArgumentException가 던져집니다. 예를 들어, 필수 QuicConnectionOptions.DefaultStreamErrorCode가 설정되지 않은 경우 ConnectAsync(QuicClientConnectionOptions, CancellationToken)을 호출하면 ArgumentOutOfRangeException가 발생합니다.
퀵리스너옵션
새 QuicListener를 시작할 때 QuicListener.ListenAsync(QuicListenerOptions, CancellationToken)에서 QuicListenerOptions이 사용됩니다. 개별 구성 속성은 다음과 같습니다.
- 애플리케이션 프로토콜
- ConnectionOptionsCallback
- ListenBacklog
- ListenEndPoint
애플리케이션 프로토콜
ApplicationProtocols 서버(RFC 7301 - ALPN)에서 허용하는 애플리케이션 프로토콜을 정의합니다. 관련이 없는 여러 프로토콜에 대한 여러 값을 포함할 수 있습니다. 새 연결을 수락하는 과정에서 수신기는 들어오는 각 연결에 대해 하나의 특정 프로토콜을 좁히거나 선택할 수 있습니다. QuicListenerOptions.ConnectionOptionsCallback참조하세요. 이 속성은 필수이며 하나 이상의 값을 포함해야 합니다.
커넥션옵션콜백
ConnectionOptionsCallback은(는) 들어오는 연결에 대해 QuicServerConnectionOptions을(를) 선택하는 대리자입니다. 이 함수는 클라이언트에서 요청한 서버 이름(RFC 6066 - SNI)을 포함하는 QuicConnection 및 SslClientHelloInfo 부분적으로 초기화된 인스턴스가 제공됩니다. 들어오는 각 연결에 대해 대리자가 호출됩니다. 제공된 클라이언트 정보에 따라 다른 옵션을 반환하거나 매번 동일한 옵션 인스턴스를 안전하게 반환할 수 있습니다. 대리자의 용도와 형태는 의도적으로 SslStream.AuthenticateAsServerAsync(ServerOptionsSelectionCallback, Object, CancellationToken)에서 사용된 ServerOptionsSelectionCallback와 비슷하게 설정되었습니다. 이 속성은 필수입니다.
듣기미완료목록
ListenBacklog 추가 연결이 거부되기 전에 수신기가 보유할 수 있는 들어오는 연결 수를 결정합니다. 연결이 실패하거나 큐에서 대기하는 동안 연결이 종료되는 경우에도 연결을 설정하려는 모든 시도가 중요합니다. 이 제한에 대한 새 연결 수를 설정하는 프로세스도 진행 중입니다. 연결 또는 연결 시도는 QuicListener.AcceptConnectionAsync(CancellationToken)을 통해 검색될 때까지 집계됩니다. 백로그 제한의 목적은 서버가 처리할 수 있는 것보다 더 많은 들어오는 연결에 의해 과부하되는 것을 방지하는 것입니다. 이 속성은 선택 사항이며 기본값은 512입니다.
리스닝 엔드포인트
ListenEndPoint 수신기가 새 연결을 수락할 IP 주소 및 포트를 포함합니다. 기본 구현으로 인해 수신기인 MsQuic
여기에 지정된 항목에 관계없이 항상 이중 스택 와일드카드 소켓에 바인딩됩니다. 이로 인해 특히 HTTP/1.1 및 HTTP/2 사례와 같은 일반 TCP 소켓과 비교하여 예기치 않은 동작이 발생할 수 있습니다. 자세한 내용은 QUIC 문제 해결 가이드참조하세요.
이 속성은 필수입니다.
퀵 연결 옵션 (QuicConnectionOptions)
QuicConnectionOptions 옵션은 QuicClientConnectionOptionsQuicServerConnectionOptions간에 공유됩니다. 추상 기본 클래스이며 자체적으로 사용할 수 없습니다. 여기에는 다음 속성이 포함됩니다.
- defaultCloseErrorCode
- DefaultStreamErrorCode
- 핸드셰이크시간초과
- 유휴 시간 초과
- 초기 수신 창 크기
- KeepAlive간격
- MaxInboundBidirectionalStreams
- 최대수신단방향스트림
- StreamCapacityCallback
DefaultCloseErrorCode (기본 닫기 오류 코드)
DefaultCloseErrorCode QuicConnection.CloseAsync(Int64, CancellationToken)호출하지 않고 연결이 삭제될 때 사용됩니다. 연결을 닫는 애플리케이션 수준 이유를 제공하기 위해 QUIC 프로토콜이 필요합니다(RFC 9000 - 연결 닫기). QuicConnection 연결을 삭제하기 전에 애플리케이션 코드가 CloseAsync(Int64, CancellationToken) 호출하도록 강제할 방법이 없습니다. 이 경우 연결에서 사용할 오류 코드를 알아야 합니다. 이 속성은 필수입니다.
DefaultStreamErrorCode (기본 스트림 오류 코드)
DefaultStreamErrorCode 모든 데이터를 읽기 전에 스트림이 삭제될 때 사용됩니다. QUIC 스트림을 통해 데이터를 수신하는 경우 애플리케이션은 모든 데이터를 사용하거나 그렇지 않은 경우 읽기 쪽을 중단해야 합니다. 연결 닫기와 마찬가지로 QUIC 프로토콜에는 읽기 쪽을 중단하는 애플리케이션 수준 이유가 필요합니다(rfC 9000 -보내기 중지). 이 속성은 필수입니다.
핸드셰이크타임아웃
HandshakeTimeout 연결을 완전히 설정해야 하는 시간 제한을 설정합니다. 그렇지 않으면 중단됩니다. 이 값을 InfiniteTimeSpan 설정할 수 있지만 권장되지 않습니다. 연결 시도가 무기한 멈춰 있을 수 있으며 QuicListener을 중지하는 방법 외에는 이를 취소할 방법이 없어. 이 속성은 선택 사항이며 기본값은 10초입니다.
IdleTimeout
지정된 IdleTimeout이상 연결이 비활성 상태이면 연결이 끊어집니다. 이 옵션은 QUIC 프로토콜 사양(RFC 9000 - 유휴 시간 제한)의 일부이며 연결 핸드셰이크 중에 피어로 전송됩니다. 그런 다음 연결은 자신의 시간 제한과 피어의 유휴 시간 제한 중 더 작은 값을 선택하여 사용합니다. 따라서 유휴 시간 제한 시 이 옵션이 설정된 것보다 빨리 연결을 닫을 수 있습니다. 이 속성은 선택 사항이며 기본값은 30초인 MsQuic을 기반으로 합니다.
초기 수신 창 크기들
InitialReceiveWindowSizes 처음에는 연결 및/또는 스트림에서 수신할 수 있는 데이터의 양을 제한하는 값 집합을 지정합니다. QUIC 프로토콜은 개별 스트림을 통해 전송할 수 있는 데이터의 양을 제한하고 전체 연결(rfC 9000- 데이터 흐름 제어)에 대해 누적적으로 전송할 수 있는 양을 제한하는 메커니즘을 정의합니다. 이러한 제한은 애플리케이션이 데이터 사용을 시작하기 전에만 적용됩니다. 그 후 MsQuic
애플리케이션에서 읽는 속도에 따라 수신 창의 크기를 지속적으로 조정합니다. 이 속성은 다음 옵션을 포함하는 QuicReceiveWindowSizes 형식입니다.
- Connection: 이 연결에 속하는 모든 스트림에서 수신된 데이터에 대한 누적 제한입니다.
- LocallyInitiatedBidirectionalStream: 나가는 양방향 스트림에서 수신된 데이터에 대한 제한입니다.
- RemotelyInitiatedBidirectionalStream: 들어오는 양방향 스트림에서 수신된 데이터에 대한 제한입니다.
- UnidirectionalStream: 들어오는 단방향 스트림에서 수신된 데이터에 대한 제한입니다.
이러한 값은 2의 거듭제곱인 음수가 아닌 정수여야 합니다. 이는 MsQuic
에서 기인한 제한 사항입니다. 이러한 값을 0으로 설정하면 기본적으로 특정 스트림 또는 연결 전체에서 데이터를 수신하지 않습니다.
이 속성은 선택 사항이며, 기본값은 스트림의 경우 64KB, 연결의 경우 64MB입니다.
KeepAliveInterval
KeepAliveInterval 연결을 활성 상태로 유지하고 IdleTimeout 닫히는 것을 방지하기 위해 PING 프레임이 전송되는지 여부와 빈도를 결정합니다(RFC 9000 - PING 프레임). 이 속성을 설정할 때는 RFC 9000 - 유휴 시간 제한지연에 대한 권장 사항을 고려하십시오. 값을 너무 낮게 설정하면 성능에 부정적인 영향을 미칠 수 있습니다. 또한 유휴 시간 제한에 너무 가깝게 속성을 설정하면 연결이 닫힐 수 있습니다. 이 속성은 선택 사항이며 기본값은 InfiniteTimeSpan PING가 전송되지 않음을 의미합니다.
MaxInboundBidirectionalStreams
MaxInboundBidirectionalStreams 연결에서 허용할 최대 동시 활성 양방향 스트림 수를 결정합니다. 이는 QUIC 사양이 동시성 처리(RFC 9000 - 동시성제어)를 정의하는 방식과 다릅니다. QUIC 프로토콜은 연결 수명 동안 누적 스트림 수를 계산하고, 계속 증가하는 제한을 사용하여 이미 닫힌 스트림(rfC 9000 -MAX_STREAMS 프레임)을 포함하여 연결에서 허용하는 전체 스트림 수를 결정합니다. 이 속성은 애플리케이션에서 동시 스트림 제한만 지정하고 MsQuic
이 제한을 해당 MAX_STREAMS
프레임으로 변환하도록 간소화합니다.
이 속성은 선택 사항이며, 기본값은 클라이언트 연결의 경우 0이고 서버 연결의 경우 100입니다.
MaxInboundUnidirectionalStreams
MaxInboundUnidirectionalStreams 연결에서 허용할 최대 동시 활성 단방향 스트림 수를 결정합니다. 이는 QUIC 사양에서 처리 스트림 동시성(rfC 9000- 동시성제어)을 정의하는 방법과 다릅니다. QUIC 프로토콜은 연결 수명 동안 누적 스트림 수를 계산하고, 계속 증가하는 제한을 사용하여 이미 닫힌 스트림(rfC 9000 -MAX_STREAMS 프레임)을 포함하여 연결에서 허용하는 전체 스트림 수를 결정합니다. 이 속성은 애플리케이션에서 동시 스트림 제한만 지정하고 MsQuic
이 제한을 해당 MAX_STREAMS
프레임으로 변환하도록 간소화합니다.
이 속성은 선택 사항이며, 기본값은 클라이언트 연결의 경우 0이고 서버 연결의 경우 10입니다.
스트림 용량 콜백
StreamCapacityCallback은 피어가 MAX_STREAMS
을 통해 새로운 스트림 용량을 해제할 때마다 호출되는 콜백으로, 그 결과 현재 용량이 0을 초과하게 됩니다. 콜백 인수에 제공된 값은 용량의 증가량을 나타냅니다. 따라서 콜백에서 제공된 모든 값의 합계는 MAX_STREAMS
로부터 받은 마지막 값(RFC 9000 - MAX_STREAMS 프레임)에 해당합니다. 이 콜백은 SocketsHttpHandler.EnableMultipleHttp3Connections 기능을 지원하도록 설계되었으며 다음과 같은 몇 가지 주의 사항이 있습니다.
- 언제든 실제 용량을 알 수 있도록 열려 있는 모든 스트림과 열린 스트림을 추적하는 것은 애플리케이션의 책임입니다.
- 콜백은 병렬로 호출될 수 있으므로 스트림 계산을 중심으로 동기화를 제대로 처리하는 것은 애플리케이션의 맡입니다.
- 첫 번째 호출(초기 용량 포함)은 QuicConnection 인스턴스가 QuicConnection.ConnectAsync(QuicClientConnectionOptions, CancellationToken) 또는 QuicListener.AcceptConnectionAsync(CancellationToken)통해 전달되기 전에 발생할 수 있습니다.
다음 간소화된 시나리오는 스트림 열기 및 콜백의 동작을 캡처합니다.
클라이언트는 다음을 통해 서버에 대한 연결을 시작합니다.
var client = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions { ... StreamCapacityCallback = (connection, args) => Console.WriteLine($"{connection} stream capacity increased by: unidi += {args.UnidirectionalIncrement}, bidi += {args.BidirectionalIncrement}") };
서버는 단방향 스트림에 대한 스트림 제한
2
및 양방향 스트림에 대한 스트림 제한0
을 클라이언트에 초기 설정으로 보냅니다.클라이언트의
StreamCapacityCallback
호출되고 인쇄됩니다.[conn][0x58575BF805B0] stream capacity increased by: unidi += 2, bidi += 0
ConnectAsync
에 대한 클라이언트 호출은[conn][0x58575BF805B0]
연결로 반환됩니다.클라이언트는 몇 가지 스트림을 열려고 시도합니다.
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);
클라이언트는 처음 두 스트림을 완료하고 닫습니다.
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")}");
클라이언트는 다음을 인쇄합니다.
Stream 3 pending
서버는 처음 두 스트림을 처리한 후
2
추가 용량을 제공합니다.클라이언트에서 두 가지 일이 발생합니다. 먼저 세 번째 스트림이 열립니다.
var stream3 = await taskStream3;
그런 다음 클라이언트의
StreamCapacityCallback
다시 호출되고 인쇄됩니다.[conn][0x58575BF805B0] stream capacity increased by: unidi += 2, bidi += 0
이 속성은 선택 사항입니다.
QuicServerConnectionOptions
QuicServerConnectionOptions 옵션은 서버 쪽 연결에 따라 다릅니다. QuicConnectionOptions상속된 속성 외에도 다음이 포함됩니다.
서버 인증 옵션
ServerAuthenticationOptions 서버 연결에 대한 TLS 설정을 포함합니다. 옵션은 SslStream.AuthenticateAsServer(SslServerAuthenticationOptions) 및 SslStream.AuthenticateAsServerAsync(SslServerAuthenticationOptions, CancellationToken)사용되는 것과 동일합니다. QUIC 서버의 경우 다음과 같은 경우 SslServerAuthenticationOptions 유효합니다.
- 다음 속성 중 하나 이상이 유효한 인증서를 반환합니다. ServerCertificateSelectionCallback, ServerCertificateContext, ServerCertificate.
- ApplicationProtocols에서 하나 이상의 애플리케이션 프로토콜이 정의됩니다.
- 변경된 경우 EncryptionPolicy가 NoEncryption로 설정되지 않습니다(기본값은 RequireEncryption).
- 설정된 경우, CipherSuitesPolicy에는 TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256 중 하나 이상이 포함됩니다(기본값은
null
이고,MsQuic
는 OS에서 지원하는 모든 QUIC 호환 암호화 스위트를 사용할 수 있습니다).
이 속성은 필수이며 나열된 조건을 충족해야 합니다.
QuicClientConnectionOptions
QuicClientConnectionOptions 옵션은 클라이언트 쪽 연결과 관련이 있습니다. QuicConnectionOptions상속된 속성 외에도 다음이 포함됩니다.
- ClientAuthenticationOptions
- 로컬 엔드포인트
- RemoteEndPoint
클라이언트 인증 옵션
ClientAuthenticationOptions 클라이언트 연결에 대한 TLS 설정을 포함합니다. 옵션은 SslStream.AuthenticateAsClient(SslClientAuthenticationOptions) 및 SslStream.AuthenticateAsClientAsync(SslClientAuthenticationOptions, CancellationToken)사용되는 것과 동일합니다. QUIC 클라이언트의 경우 다음과 같은 경우 SslClientAuthenticationOptions 유효합니다.
- ApplicationProtocols에서 적어도 하나의 애플리케이션 프로토콜이 정의됩니다.
- 변경된 경우 EncryptionPolicy가 NoEncryption로 설정되지 않습니다(기본값은 RequireEncryption).
- 설정된 경우, CipherSuitesPolicy에는 TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256 중 적어도 하나가 포함됩니다. (기본값은
null
이며,MsQuic
가 OS에서 지원하는 모든 QUIC 호환 암호 그룹을 사용할 수 있도록 합니다.)
이 속성은 필수이며 나열된 조건을 충족해야 합니다.
LocalEndPoint (로컬 엔드포인트)
LocalEndPoint 클라이언트 연결이 바인딩할 IP 주소 및 포트를 포함합니다. 지정하지 않으면 OS는 IP 주소와 포트를 할당합니다. 이 속성은 선택 사항입니다.
RemoteEndPoint
RemoteEndPoint는 연결이 설정되는 피어의 DnsEndPoint일 수도 있고, IPEndPoint일 수도 있습니다. DnsEndPoint일 경우, Dns.GetHostAddressesAsync(String, CancellationToken)이 반환한 첫 번째 IP 주소가 사용됩니다. 이 속성은 필수입니다.
.NET