Skip to content

Commit 3ac6024

Browse files
committed
📝 Further improve readme/docs
1 parent e176129 commit 3ac6024

3 files changed

Lines changed: 132 additions & 15 deletions

File tree

readme.md

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
[![License](https://img.shields.io/github/license/devlooped/WebSocketPipe.svg?color=blue)](https://github.com/devlooped/WebSocketPipe/blob/main/license.txt)
77
[![Build](https://github.com/devlooped/WebSocketPipe/workflows/build/badge.svg?branch=main)](https://github.com/devlooped/WebSocketPipe/actions)
88

9-
A System.IO.Pipelines adapter API over System.Net.WebSockets
10-
119
# Usage
1210

1311
```csharp
@@ -20,27 +18,35 @@ using IWebSocketPipe pipe = WebSocketPipe.Create(client, closeWhenCompleted: tru
2018

2119
// Start the pipe before hooking up the processing
2220
var run = pipe.RunAsync();
21+
```
2322

24-
// Wait for completion of processing code
25-
await Task.WhenAny(
26-
ReadIncoming(pipe.Input),
27-
SendOutgoing(pipe.Output));
23+
The `IWebSocketPipe` interface extends [IDuplexPipe](https://docs.microsoft.com/en-us/dotnet/api/system.io.pipelines.iduplexpipe?view=dotnet-plat-ext-5.0),
24+
exposing `Input` and `Output` properties that can be used to
25+
read incoming messages and write outgoing ones.
26+
27+
For example, to read incoming data and write it to the console,
28+
we could write the following code:
2829

29-
// When the processing completes, the overall pipe run will also complete
30-
await run;
30+
```csharp
31+
await ReadIncoming(pipe.Input);
3132

32-
// Reads incoming data and writes to the console
3333
async Task ReadIncoming(PipeReader reader)
3434
{
3535
while (await reader.ReadAsync() is var result && !result.IsCompleted)
3636
{
3737
Console.WriteLine($"Received: {Encoding.UTF8.GetString(result.Buffer)}");
38-
reader.AdvanceTo(result.Buffer.Start, result.Buffer.End);
38+
reader.AdvanceTo(result.Buffer.End);
3939
}
4040
Console.WriteLine($"Done reading.");
4141
}
42+
```
43+
44+
Similarly, to write to the underlying websocket the input
45+
entered in the console, we use code like the following:
46+
47+
```csharp
48+
await SendOutgoing(pipe.Output);
4249

43-
// Reads console input and writes to pipe until an empty line is entered
4450
async Task SendOutgoing(PipeWriter writer)
4551
{
4652
while (Console.ReadLine() is var line && line?.Length > 0)
@@ -52,3 +58,32 @@ async Task SendOutgoing(PipeWriter writer)
5258
}
5359
```
5460

61+
If we wanted to simultaneously read and write and wait for
62+
completion of both operations, we could just wait for both
63+
tasks:
64+
65+
```csharp
66+
// Wait for completion of processing code
67+
await Task.WhenAny(
68+
ReadIncoming(pipe.Input),
69+
SendOutgoing(pipe.Output));
70+
```
71+
72+
Note that completing the `PipeWriter` automatically causes the
73+
reader to reveive a completed result and exit the loop. In addition,
74+
the overall `IWebSocketPipe.RunAsync` task will also run to completion.
75+
76+
77+
The `IWebSocketPipe` takes care of gracefully closing the connection
78+
when the input or output are completed, if `closeWhenCompleted` is set
79+
to true when creating it.
80+
81+
Alternatively, it's also possible to complete the entire pipe explicitly,
82+
while setting an optional socket close status and status description for
83+
the server to act on:
84+
85+
```csharp
86+
await pipe.CompleteAsync(WebSocketCloseStatus.NormalClosure, "Done processing");
87+
```
88+
89+
Specifying a close status will always close the underlying socket.

src/WebSocketPipe/WebSocketPipe.csproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,4 @@
1313
<PackageReference Include="System.IO.Pipelines" Version="5.0.1" />
1414
</ItemGroup>
1515

16-
<ItemGroup>
17-
<None Include="..\..\readme.md" Link="readme.md" Pack="true" PackagePath="readme.md" />
18-
</ItemGroup>
19-
2016
</Project>

src/WebSocketPipe/readme.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
[![Version](https://img.shields.io/nuget/vpre/WebSocketPipe.svg?color=royalblue)](https://www.nuget.org/packages/WebSocketPipe)
2+
[![Downloads](https://img.shields.io/nuget/dt/WebSocketPipe.svg?color=green)](https://www.nuget.org/packages/WebSocketPipe)
3+
[![License](https://img.shields.io/github/license/devlooped/WebSocketPipe.svg?color=blue)](https://github.com/devlooped/WebSocketPipe/blob/main/license.txt)
4+
[![Build](https://github.com/devlooped/WebSocketPipe/workflows/build/badge.svg?branch=main)](https://github.com/devlooped/WebSocketPipe/actions)
5+
6+
# Usage
7+
8+
```csharp
9+
using Devlooped;
10+
11+
var client = new ClientWebSocket();
12+
await client.ConnectAsync(serverUri, CancellationToken.None);
13+
14+
using IWebSocketPipe pipe = WebSocketPipe.Create(client, closeWhenCompleted: true);
15+
16+
// Start the pipe before hooking up the processing
17+
var run = pipe.RunAsync();
18+
```
19+
20+
The `IWebSocketPipe` interface extends [IDuplexPipe](https://docs.microsoft.com/en-us/dotnet/api/system.io.pipelines.iduplexpipe?view=dotnet-plat-ext-5.0),
21+
exposing `Input` and `Output` properties that can be used to
22+
read incoming messages and write outgoing ones.
23+
24+
For example, to read incoming data and write it to the console,
25+
we could write the following code:
26+
27+
```csharp
28+
await ReadIncoming(pipe.Input);
29+
30+
async Task ReadIncoming(PipeReader reader)
31+
{
32+
while (await reader.ReadAsync() is var result && !result.IsCompleted)
33+
{
34+
Console.WriteLine($"Received: {Encoding.UTF8.GetString(result.Buffer)}");
35+
reader.AdvanceTo(result.Buffer.End);
36+
}
37+
Console.WriteLine($"Done reading.");
38+
}
39+
```
40+
41+
Similarly, to write to the underlying websocket the input
42+
entered in the console, we use code like the following:
43+
44+
```csharp
45+
await SendOutgoing(pipe.Output);
46+
47+
async Task SendOutgoing(PipeWriter writer)
48+
{
49+
while (Console.ReadLine() is var line && line?.Length > 0)
50+
{
51+
Encoding.UTF8.GetBytes(line, writer);
52+
}
53+
await writer.CompleteAsync();
54+
Console.WriteLine($"Done writing.");
55+
}
56+
```
57+
58+
If we wanted to simultaneously read and write and wait for
59+
completion of both operations, we could just wait for both
60+
tasks:
61+
62+
```csharp
63+
// Wait for completion of processing code
64+
await Task.WhenAny(
65+
ReadIncoming(pipe.Input),
66+
SendOutgoing(pipe.Output));
67+
```
68+
69+
Note that completing the `PipeWriter` automatically causes the
70+
reader to reveive a completed result and exit the loop. In addition,
71+
the overall `IWebSocketPipe.RunAsync` task will also run to completion.
72+
73+
74+
The `IWebSocketPipe` takes care of gracefully closing the connection
75+
when the input or output are completed, if `closeWhenCompleted` is set
76+
to true when creating it.
77+
78+
Alternatively, it's also possible to complete the entire pipe explicitly,
79+
while setting an optional socket close status and status description for
80+
the server to act on:
81+
82+
```csharp
83+
await pipe.CompleteAsync(WebSocketCloseStatus.NormalClosure, "Done processing");
84+
```
85+
86+
Specifying a close status will always close the underlying socket.

0 commit comments

Comments
 (0)