以上就是服务端的完整代码了 。
接下来我们看一下客户端 QuicClient 的代码 。
直接使用 QuicConnection.ConnectAsync 连接到服务端 。
Console.WriteLine("Quic Client Running...");await Task.Delay(3000);// 连接到服务端var connection = await QuicConnection.ConnectAsync(new QuicClientConnectionOptions{DefaultCloseErrorCode = 0,DefaultStreamErrorCode = 0,RemoteEndPoint = new IPEndPoint(IPAddress.Loopback, 9999),ClientAuthenticationOptions = new SslClientAuthenticationOptions{ApplicationProtocols = new List<SslApplicationProtocol> { SslApplicationProtocol.Http3 },RemoteCertificateValidationCallback = (sender, certificate, chain, errors) =>{return true;}}});
创建一个出站的双向流 。
// 打开一个出站的双向流var stream = await connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional); var reader = PipeReader.Create(stream);var writer = PipeWriter.Create(stream);
后台读取流数据,然后循环写入数据 。
// 后台读取流数据_ = ProcessLinesAsync(stream);Console.WriteLine(); // 写入数据for (int i = 0; i < 7; i++){await Task.Delay(2000);var message = $"Hello Quic {i} \n";Console.Write("Send -> " + message);await writer.WriteAsync(Encoding.UTF8.GetBytes(message));}await writer.CompleteAsync(); Console.ReadKey();
ProcessLinesAsync 和服务端一样,使用System.IO.Pipeline读取流数据 。
async Task ProcessLinesAsync(QuicStream stream){while (true){ReadResult result = await reader.ReadAsync();ReadOnlySequence<byte> buffer = result.Buffer;while (TryReadLine(ref buffer, out ReadOnlySequence<byte> line)){// 处理行数据ProcessLine(line);}reader.AdvanceTo(buffer.Start, buffer.End);if (result.IsCompleted){break;}}await reader.CompleteAsync();await writer.CompleteAsync();} bool TryReadLine(ref ReadOnlySequence<byte> buffer, out ReadOnlySequence<byte> line){SequencePosition? position = buffer.PositionOf((byte)'\n');if (position == null){line = default;return false;}line = buffer.Slice(0, position.Value);buffer = buffer.Slice(buffer.GetPosition(1, position.Value));return true;}void ProcessLine(in ReadOnlySequence<byte> buffer){foreach (var segment in buffer){Console.Write("Recevied -> " + System.Text.Encoding.UTF8.GetString(segment.Span));Console.WriteLine();}Console.WriteLine();}
到这里,客户端和服务端的代码都完成了,客户端使用Quic 流发送了一些消息给服务端,服务端收到消息后在控制台输出 , 并回复一个 Ack 消息,因为我们创建了一个双向流 。
程序的运行结果如下
文章插图
我们上面说到了一个 QuicConnection 可以创建多个流 , 并行传输数据 。
改造一下服务端的代码,支持接收多个 Quic 流 。
var cts = new CancellationTokenSource();while (!cts.IsCancellationRequested){var stream = await connection.AcceptInboundStreamAsync();Console.WriteLine($"Stream [{stream.Id}]: created");Console.WriteLine();_ = ProcessLinesAsync(stream);} Console.ReadKey();
对于客户端 , 我们用多个线程创建多个 Quic 流,并同时发送消息 。默认情况下,一个 Quic 连接的流的限制是 100,当然你可以设置 QuicConnectionOptions 的 MaxInboundBidirectionalStreams 和 MaxInboundUnidirectionalStreams 参数 。
for (int j = 0; j < 5; j++){_ = Task.Run(async () => {// 创建一个出站的双向流var stream = await connection.OpenOutboundStreamAsync(QuicStreamType.Bidirectional);var writer = PipeWriter.Create(stream);Console.WriteLine();await Task.Delay(2000);var message = $"Hello Quic [{stream.Id}] \n";Console.Write("Send -> " + message);await writer.WriteAsync(Encoding.UTF8.GetBytes(message));await writer.CompleteAsync();});}
最终程序的输出如下【基于 .NET 7 的 QUIC 实现 Echo 服务】
文章插图
完整的代码可以在下面的 github 地址找到,希望对您有用!
https://github.com/SpringLeee/PlayQuic
扫码关注【半栈程序员】,获取最新文章 。
文章插图
推荐阅读
- <一>类,对象,this指针
- 《ASP.NET Core技术内幕与项目实战》精简集-目录
- 暗区突围SVDS怎么改
- 巧克力中的劳斯莱斯|让迪拜皇室神魂颠倒的Patchi巧克力
- iphone12pro max打王者发烫掉帧是真的吗?
- lookfantastic被税退运全攻略
- 英雄杀内奸怎么玩(英雄杀里内奸是干嘛的)
- 游戏工作室真的赚钱吗(游戏工作室)
- 游戏工作室盈利模式(月入10万的创业工作室)
- 10 天龙八部游戏工作室是如何赚钱的(天龙八部单机游戏商人攻略)