Search  
Always will be ready notify the world about expectations as easy as possible: job change page
Nov 30, 2023

How to Use QUIC (Quick UDP Internet Connections) in .NET 7

Author:
Source:
Views:
1036

QUIC (Quick UDP Internet Connections) is a new transport protocol for the Internet that runs on top of User Datagram Protocol (UDP)

Night city

QUIC (Quick UDP Internet Connections) is a new transport protocol for the Internet that runs on top of User Datagram Protocol (UDP). It is designed to provide a secure, low-latency, and multiplexed connection between client and server. QUIC aims to improve upon the traditional Transmission Control Protocol (TCP) by reducing the number of round trips required for connection establishment and data transfer, which results in faster page load times and improved user experience.

Why QUIC

QUIC was invented to address the limitations and inefficiencies of the traditional Transmission Control Protocol (TCP) in today’s fast-paced Internet environment. With the increasing use of mobile devices and the need for instant gratification, the traditional TCP has become a bottleneck for delivering fast, reliable and secure online experiences.

QUIC was designed to address these issues by providing a low-latency, multiplexed, and secure transport protocol that can improve the performance and reliability of the Internet. It combines the features of TCP and User Datagram Protocol (UDP) to reduce latency and improve reliability, while adding encryption and multiplexing capabilities. The result is a transport protocol that provides faster and more secure connections compared to traditional TCP.

How it works

QUIC (Quick UDP Internet Connections)

QUIC (Quick UDP Internet Connections) works by creating a secure and reliable connection between a client and a server using User Datagram Protocol (UDP). It uses encryption to protect the data being transmitted, which eliminates the need for a separate security layer like SSL/TLS.

QUIC also uses multiplexing to allow multiple streams of data to be sent over the same connection concurrently, reducing the overhead associated with multiple connections. This eliminates the need for the client to wait for a response from the server before sending additional requests, which improves the overall efficiency of the connection.

QUIC also implements congestion control, which adjusts the flow of data based on network conditions to prevent overloading the network. This results in a faster and more stable connection compared to traditional TCP.

Overall, QUIC provides a fast, secure, and reliable transport protocol for the Internet by combining the best features of TCP and UDP and adding new features to improve the performance and reliability of the connection.

QUIC handshake

QUIC in .Net 7

QUIC (Quick UDP Internet Connections) is supported in .NET 7, which is the latest version of the .NET platform developed by Microsoft. .NET 7 provides support for QUIC in the System.Net.Quic namespace, which provides a set of APIs for creating and managing QUIC connections.

With .NET 7, developers can easily create client and server applications that use QUIC as the transport protocol. They can also take advantage of the benefits provided by QUIC, such as low latency, high performance, and improved security, to build high-quality, fast, and reliable applications.

To use QUIC in .NET 7, developers can start by creating a client or server application and using the System.Net.Quic namespace to create and manage QUIC connections. They can also configure the QUIC connection to match their specific requirements, such as encryption and congestion control.

The support for QUIC in .NET 7 provides developers with a powerful and flexible platform for building fast, reliable, and secure applications that take advantage of the benefits of QUIC as a transport protocol.

An Example

Here’s a simple example to demonstrate how to use QUIC in .NET 7:

Server side:

using System;
using System.Net;
using System.Net.Quic;
using System.Net.Security;
using System.Runtime.Versioning;
using System.Security.Cryptography.X509Certificates;
using System.Text;
#pragma warning disable CA1416

namespace QuicExample
{
    [RequiresPreviewFeatures]
    class Program
    {
        static async Task Main(string[] args)
        {
            var isRunning = true;

            if (!QuicListener.IsSupported)
            {
                Console.WriteLine("QUIC is not supported.");
                return;
            }
            var protocol = "quic-test";
            //change to your pfx file path
            var pfxFilePath = "D:\\Medium\\QuicExample\\contoso.com.pfx";
            //change to your pfx file password
            var pfxPassword = "password";
            var port = 8000;

            var serverConnectionOptions = new QuicServerConnectionOptions()
            {
                DefaultStreamErrorCode = 0x0A,
                DefaultCloseErrorCode = 0x0B,                         
                ServerAuthenticationOptions = new SslServerAuthenticationOptions
                {
                    ApplicationProtocols = new List<SslApplicationProtocol>() { new SslApplicationProtocol(protocol) },                    
                    ServerCertificate = new X509Certificate2(pfxFilePath, pfxPassword)
                }
            };            

            var listener = await QuicListener.ListenAsync(new QuicListenerOptions()
            {
                ListenEndPoint = new IPEndPoint(IPAddress.Loopback, port),
                ApplicationProtocols = new List<SslApplicationProtocol>() { new SslApplicationProtocol(protocol) },
                ConnectionOptionsCallback = (_, _, _) => ValueTask.FromResult(serverConnectionOptions)
            });           


            while (isRunning)
            {
                var connection = await listener.AcceptConnectionAsync();
                var stream = await connection.AcceptInboundStreamAsync();
                
                // Work with the incoming stream ...
                var buf = new byte[128];
                var len = await stream.ReadAsync(buf, 0, buf.Length);
                Console.WriteLine(Encoding.UTF8.GetString(buf, 0, len));                
            }

            await listener.DisposeAsync();
        }
    }
}

Server side requires a certificate. You can create a self-signed certificate using PowerShell:

First create the certificate:

New-SelfSignedCertificate -DnsName @("contoso.com", "www.contoso.com") -CertStoreLocation "cert:\LocalMachine\My"

Then export the certificate:

$certKeyPath = "D:\Medium\QuicExample\contoso.com.pfx"
$password = ConvertTo-SecureString 'password' -AsPlainText -Force
$cert | Export-PfxCertificate -FilePath $certKeyPath -Password $password
$rootCert = $(Import-PfxCertificate -FilePath $certKeyPath -CertStoreLocation 'Cert:\LocalMachine\Root' -Password $password)

Client side:

using System;
using System.Net;
using System.Net.Quic;
using System.Net.Security;
using System.Runtime.Versioning;
using System.Security.Cryptography.X509Certificates;
using System.Text;
#pragma warning disable CA1416

namespace QuickClientExample
{
    [RequiresPreviewFeatures]
    class Program
    {
        static async Task Main(string[] args)
        {            

            if (!QuicConnection.IsSupported)
            {
                Console.WriteLine("QUIC is not supported.");
                return;
            }

            var protocol = "quic-test";
            var port = 8000;

            var clientConnectionOptions = new QuicClientConnectionOptions()
            {
                RemoteEndPoint = new IPEndPoint(IPAddress.Loopback, port),
                DefaultStreamErrorCode = 0x0A,
                DefaultCloseErrorCode = 0x0B,
                MaxInboundUnidirectionalStreams = 10,
                MaxInboundBidirectionalStreams = 100,
                ClientAuthenticationOptions = new SslClientAuthenticationOptions()
                {
                    ApplicationProtocols = new List<SslApplicationProtocol>() { new SslApplicationProtocol(protocol) }
                }
            };
            var connection = await QuicConnection.ConnectAsync(clientConnectionOptions);
            var outgoingStream = await connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional);

            var str = "hello world";
            var buf = Encoding.UTF8.GetBytes(str);
            await outgoingStream.WriteAsync(buf, 0, buf.Length);

            Console.ReadKey();

            await connection.CloseAsync(0x0C);
            await connection.DisposeAsync();
        }
    }
}

The example above helps to illustrate some fundamental concepts of the QUIC protocol, such as the use of application protocols, connections, and streams.

You might get a firwall alert when you first time run it.

Windows Security Alert

An application protocol is a set of rules and conventions that govern the exchange of data between a client and a server. Each QUIC connection can support multiple application protocols, each of which is identified by a unique protocol ID. This allows different applications to share the same connection while still maintaining independent streams of data.

A connection in QUIC is a logical connection between a client and a server that provides a reliable and secure transport for exchanging data. Unlike traditional TCP connections, which are based on a single stream of data, QUIC connections can support multiple streams of data in parallel. This allows for more efficient use of network resources and faster data transfer speeds.

A stream in QUIC is a unidirectional or bidirectional flow of data within a connection. Each stream is identified by a unique stream ID, which is used to associate data with a particular stream. Streams can be opened and closed dynamically as needed, allowing applications to send and receive data independently of each other. This provides greater flexibility and control over the data being exchanged, as well as the ability to prioritize different types of data based on their importance.

Together, these concepts provide a powerful and flexible framework for exchanging data over the Internet with the QUIC protocol. By providing a reliable and secure transport, multiple application protocols, and multiple streams of data within a single connection, QUIC allows for more efficient and faster data transfer, improving the overall performance and user experience of Internet applications.

QUIC Protocol
 |
 +-- Protocal 1
 |    |
 |    +-- Connection
 |    |    |
 |    |    +-- Stream
 |    |    |
 |    |    +-- Stream
 |    |    |
 |    |    +-- Stream
 |    |    |
 |    |    ...
 |    |
 |    +-- Connection
 |         |
 |         +-- Stream
 |         |
 |         +-- Stream
 |         |
 |         +-- Stream
 |         |
 |         ...
 |
 +-- Protocol 2
      |
      +-- Connection
           |
           +-- Stream
           |
           +-- Stream
           |
           +-- Stream
           |
           ...

The support for QUIC in .NET 7 is a significant step forward for the .NET ecosystem and the wider internet, as it enables the development of fast and reliable applications. Overall, the addition of QUIC support in .NET 7 is a positive development for both developers and users, as it opens up new possibilities for building fast and efficient applications.

GitHub: https://github.com/devedium/QuicExample

***

References

Similar
Jul 8, 2021
Author: Christophe Nasarre
In the context of helping the teams at Criteo to clean up our code base, I gathered and documented a few C# anti-patterns similar to Kevin’s publication about performance code smell. Here is an extract related to good/bad memory patterns.Even...
Feb 1
Author: Sohail Aslam
IntroductionWelcome to the world of C#! Whether you’re a seasoned developer or just starting your programming journey, the power and versatility of C# can elevate your coding experience. In this article, we’ll explore a curated collection of tips and tricks...
Apr 8
Author: João Simões
Performance comparison between LinkedList and ToArraySome weeks ago I created an article comparing the performance of ToList versus ToArray when creating short lived collections that won’t be mutated, usually used to prevent multiple enumerations when iterating over a temporary LINQ...
Mar 18
Author: codezone
File reading operations in C# are crucial for many applications, often requiring efficiency and optimal performance. When handling file reading tasks, employing the right strategies can significantly impact the speed and resource utilization of your application. Here are some best...
Send message
Email
Your name
*Message


© 1999–2024 WebDynamics
1980–... Sergey Drozdov
Area of interests: .NET Framework | .NET Core | C# | ASP.NET | Windows Forms | WPF | HTML5 | CSS3 | jQuery | AJAX | Angular | React | MS SQL Server | Transact-SQL | ADO.NET | Entity Framework | IIS | OOP | OOA | OOD | WCF | WPF | MSMQ | MVC | MVP | MVVM | Design Patterns | Enterprise Architecture | Scrum | Kanban