Skip to content

Commit 36bdcfc

Browse files
committed
move index page
1 parent 79e8789 commit 36bdcfc

File tree

2 files changed

+70
-135
lines changed

2 files changed

+70
-135
lines changed

docs/index.md

+1-96
Original file line numberDiff line numberDiff line change
@@ -1,96 +1 @@
1-
# What is protobuf-net.GrpcLite?
2-
3-
It is a drop in protocol replacement for gRPC; the .NET gRPC API has no hard bindings to either the marshaller or the underlying transport; protobuf-net.Grpc offered ways to change the marshaller (for example,
4-
allowing you to use protobuf-net) - and now protobuf-net.GrpcLite allows you to change the transport - from HTTP/2 to a custom transport *inspired* by HTTP/2, but simpler and with lower overheads. It is also
5-
fully managed, unlike HTTP/2 which often required unmanaged library or OS support.
6-
7-
The transport *is not compatible* with regular HTTP/2 gRPC, but: all of your existing gRPC code should continue to function, as long as you have a client and server that can talk the same dialect.
8-
9-
## How do I use it?
10-
11-
At the client, instead of using `var channel = new Channel(...);` (unmanaged HTTP/2) or `var channel = GrpcChannel.ForAddress(...);` (managed HTTP/2), you would use something like:
12-
13-
``` c#
14-
using var channel = await ConnectionFactory.ConnectSocket(endPoint).AsFrames().CreateChannelAsync();
15-
```
16-
17-
The rest of your client code *shouldn't change at all*. This is just one example; other terminators are possible - for example, anything that can provide a `Stream` should work, including support
18-
for things like TLS, compression, named pipes, etc.
19-
20-
At the server, the code is currently a bit closer to the unmanaged server implementation (the server does not integrate deeply into Kestrel, although it works fine inside a Kestrel process); service-binding
21-
is via the `.ServiceBinder`:
22-
23-
``` c#
24-
var server = new LiteServer();
25-
server.ServiceBinder.Bind(new MyService()); // contract-first example, generated via protoc
26-
27-
// alternative if not also using protobuf-net.Grpc, which provides the Bind API
28-
// YourService.BindService(server.ServiceBinder, new MyService());
29-
30-
_ = server.ListenAsync(ConnectionFactory.ListenSocket(endpoint).AsStream().AsFrames());
31-
// ... note: leave your server running here, until you're ready to exit!
32-
server.Stop();
33-
```
34-
35-
The `ListenAsync` call will listen for multiple connections; a single server can listen to many connections on many different listeneres at once - for example, you could
36-
listen to multiple TCP ports, with/without TLS. Your `MyService` instance will be activated just like it would have been with the unmanaged server host.
37-
38-
## How do I use TLS?
39-
40-
TLS is provided via `SslStream`, and works with or without client certificates; the `WithTls()` connector optionally accepts callbacks for providing user certificates (client), or
41-
validating remote certificates (client or server); the `AuthenticateAsServer()` connector accepts a server certificate, and optionally demands client certificates; for example:
42-
43-
``` c#
44-
// TCP server; no TLS
45-
_ = server.ListenAsync(ConnectionFactory.ListenSocket(endpoint).AsStream().AsFrames());
46-
// TCP server; TLS, no client certs
47-
_ = server.ListenAsync(ConnectionFactory.ListenSocket(endpoint).AsStream().WithTls().AuthenticateAsServer(serverCert).AsFrames());
48-
// TCP server; TLS, client certs (validated via userCheck)
49-
_ = server.ListenAsync(ConnectionFactory.ListenSocket(endpoint).AsStream().WithTls(userCheck).AuthenticateAsServer(serverCert, clientCertificateRequired: true).AsFrames());
50-
51-
52-
``` c#
53-
// TCP client; no TLS
54-
using var channel = await ConnectionFactory.ConnectSocket(endPoint).AsFrames().CreateChannelAsync();
55-
// TCP client; TLS, using default server validation and certificate selection
56-
using var channel = await ConnectionFactory.ConnectSocket(endpoint).AsStream().WithTls().AuthenticateAsClient("mytestserver").AsFrames().CreateChannelAsync();
57-
// TCP client; TLS, using custom server validation and certificate selection
58-
using var channel = await ConnectionFactory.ConnectSocket(endpoint).AsStream().WithTls(serverCheck, certSelector).AuthenticateAsClient("mytestserver").AsFrames().CreateChannelAsync();
59-
```
60-
61-
## How do I use code-first?
62-
63-
At the client, code-first works exactly as it always has; just use the `.CreateClient<TService>()` method on the channel.
64-
65-
As the server, binding code-first serves to the custom server is uses the `.Binder` API:
66-
67-
``` c#
68-
server.ServiceBinder.AddCodeFirst(...);
69-
```
70-
71-
## How do I use interceptors?
72-
73-
Client-side interceptors work exactly like they do in all scenarios.
74-
75-
To register a server-side interceptor, the `Intercept()` API is used alongside the `.ServiceBinder`:
76-
77-
``` c#
78-
server.ServiceBinder.Intercept(...).Bind(new MyService()); // contract-first example, generated via protoc
79-
server.ServiceBinder.Intercept(...).AddCodeFirst(...); // code-first
80-
81-
// alternative for contract-first if not also using protobuf-net.Grpc, which provides the Bind API
82-
// YourService.BindService(server.ServiceBinder.Intercept(...), new MyService());
83-
```
84-
85-
## Other notes
86-
87-
It currently targets .NET Framework 4.7.2 up to .NET 6.0, using newer features when available. It is still very experimental - but most core things should work; feedback is welcome.
88-
89-
Known gaps:
90-
91-
- gRPC auth (although transport auth works fine)
92-
- per-stream service activation (rather than singleton)
93-
- testing needs more coverage
94-
- per-stream backoff negotiation; designed, not yet implemented
95-
- for some reason the server implementation isn't working 100% with SAEA currently - hence `.AsStream().AsFrames()` instead of just `.AsFrames()`
96-
- open question around interceptor order
1+
TODO

readme.md

+69-39
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,96 @@
1-
# <img src="https://protogen.marcgravell.com/images/protobuf-net.svg" alt="protobuf-net logo" width="45" height="45"> protobuf-net.Grpc
1+
# What is protobuf-net.GrpcLite?
22

3-
[![Build status](https://ci.appveyor.com/api/projects/status/en9i5mp471ci6ip3/branch/main?svg=true)](https://ci.appveyor.com/project/StackExchange/protobuf-net-grpc/branch/main)
3+
It is a drop in protocol replacement for gRPC; the .NET gRPC API has no hard bindings to either the marshaller or the underlying transport; protobuf-net.Grpc offered ways to change the marshaller (for example,
4+
allowing you to use protobuf-net) - and now protobuf-net.GrpcLite allows you to change the transport - from HTTP/2 to a custom transport *inspired* by HTTP/2, but simpler and with lower overheads. It is also
5+
fully managed, unlike HTTP/2 which often required unmanaged library or OS support.
46

5-
`protobuf-net.Grpc` adds code-first support for services over gRPC using either the native `Grpc.Core` API, or the fully-managed `Grpc.Net.Client` / `Grpc.AspNetCore.Server` API.
7+
The transport *is not compatible* with regular HTTP/2 gRPC, but: all of your existing gRPC code should continue to function, as long as you have a client and server that can talk the same dialect.
68

7-
It should work on all .NET languages that can generate something *even remotely like* a regular .NET type model.
9+
## How do I use it?
810

9-
- [Getting Started](https://protobuf-net.github.io/protobuf-net.Grpc/gettingstarted)
10-
- [All Documentation](https://protobuf-net.github.io/protobuf-net.Grpc/)
11-
- [Build/usage available via `protobuf-net.BuildTools`](https://protobuf-net.github.io/protobuf-net/build_tools)
12-
13-
Usage is as simple as declaring an interface for your service-contract:
11+
At the client, instead of using `var channel = new Channel(...);` (unmanaged HTTP/2) or `var channel = GrpcChannel.ForAddress(...);` (managed HTTP/2), you would use something like:
1412

1513
``` c#
16-
[ServiceContract]
17-
public interface IMyAmazingService {
18-
ValueTask<SearchResponse> SearchAsync(SearchRequest request);
19-
// ...
20-
}
14+
using var channel = await ConnectionFactory.ConnectSocket(endPoint).AsFrames().CreateChannelAsync();
2115
```
2216

23-
then either implementing that interface for a server:
17+
The rest of your client code *shouldn't change at all*. This is just one example; other terminators are possible - for example, anything that can provide a `Stream` should work, including support
18+
for things like TLS, compression, named pipes, etc.
19+
20+
At the server, the code is currently a bit closer to the unmanaged server implementation (the server does not integrate deeply into Kestrel, although it works fine inside a Kestrel process); service-binding
21+
is via the `.ServiceBinder`:
2422

2523
``` c#
26-
public class MyServer : IMyAmazingService {
27-
// ...
28-
}
24+
var server = new LiteServer();
25+
server.ServiceBinder.Bind(new MyService()); // contract-first example, generated via protoc
26+
27+
// alternative if not also using protobuf-net.Grpc, which provides the Bind API
28+
// YourService.BindService(server.ServiceBinder, new MyService());
29+
30+
_ = server.ListenAsync(ConnectionFactory.ListenSocket(endpoint).AsStream().AsFrames());
31+
// ... note: leave your server running here, until you're ready to exit!
32+
server.Stop();
2933
```
3034

31-
or asking the system for a client:
35+
The `ListenAsync` call will listen for multiple connections; a single server can listen to many connections on many different listeneres at once - for example, you could
36+
listen to multiple TCP ports, with/without TLS. Your `MyService` instance will be activated just like it would have been with the unmanaged server host.
37+
38+
## How do I use TLS?
39+
40+
TLS is provided via `SslStream`, and works with or without client certificates; the `WithTls()` connector optionally accepts callbacks for providing user certificates (client), or
41+
validating remote certificates (client or server); the `AuthenticateAsServer()` connector accepts a server certificate, and optionally demands client certificates; for example:
42+
43+
``` c#
44+
// TCP server; no TLS
45+
_ = server.ListenAsync(ConnectionFactory.ListenSocket(endpoint).AsStream().AsFrames());
46+
// TCP server; TLS, no client certs
47+
_ = server.ListenAsync(ConnectionFactory.ListenSocket(endpoint).AsStream().WithTls().AuthenticateAsServer(serverCert).AsFrames());
48+
// TCP server; TLS, client certs (validated via userCheck)
49+
_ = server.ListenAsync(ConnectionFactory.ListenSocket(endpoint).AsStream().WithTls(userCheck).AuthenticateAsServer(serverCert, clientCertificateRequired: true).AsFrames());
50+
3251

3352
``` c#
34-
var client = http.CreateGrpcService<IMyAmazingService>();
35-
var results = await client.SearchAsync(request);
53+
// TCP client; no TLS
54+
using var channel = await ConnectionFactory.ConnectSocket(endPoint).AsFrames().CreateChannelAsync();
55+
// TCP client; TLS, using default server validation and certificate selection
56+
using var channel = await ConnectionFactory.ConnectSocket(endpoint).AsStream().WithTls().AuthenticateAsClient("mytestserver").AsFrames().CreateChannelAsync();
57+
// TCP client; TLS, using custom server validation and certificate selection
58+
using var channel = await ConnectionFactory.ConnectSocket(endpoint).AsStream().WithTls(serverCheck, certSelector).AuthenticateAsClient("mytestserver").AsFrames().CreateChannelAsync();
3659
```
3760

38-
This would be equivalent to the service in .proto:
61+
## How do I use code-first?
62+
63+
At the client, code-first works exactly as it always has; just use the `.CreateClient<TService>()` method on the channel.
64+
65+
As the server, binding code-first serves to the custom server is uses the `.Binder` API:
3966

40-
``` proto
41-
service MyAmazingService {
42-
rpc Search (SearchRequest) returns (SearchResponse) {}
43-
// ...
44-
}
67+
``` c#
68+
server.ServiceBinder.AddCodeFirst(...);
4569
```
4670

47-
Obviously you need to tell it the uri etc - see [Getting Started](https://protobuf-net.github.io/protobuf-net.Grpc/gettingstarted). Usually the configuration is convention-based, but
48-
if you prefer: there are [various configuration options](https://protobuf-net.github.io/protobuf-net.Grpc/configuration).
71+
## How do I use interceptors?
4972

50-
## Getting hold of it
73+
Client-side interceptors work exactly like they do in all scenarios.
5174

52-
Everything is available as pre-built packages on nuget; in particular, you probably want one of:
75+
To register a server-side interceptor, the `Intercept()` API is used alongside the `.ServiceBinder`:
5376

54-
- [`protobuf-net.Grpc.AspNetCore`](https://www.nuget.org/packages/protobuf-net.Grpc.AspNetCore) for servers using ASP.NET Core 3.1
55-
- [`protobuf-net.Grpc.Native`](https://www.nuget.org/packages/protobuf-net.Grpc.Native) for clients or servers using the native/unmanaged API
56-
- [`protobuf-net.Grpc`](https://www.nuget.org/packages/protobuf-net.Grpc) and [`Grpc.Net.Client`](https://www.nuget.org/packages/Grpc.Net.Client/) for clients using `HttpClient` on .NET Core 3.1
77+
``` c#
78+
server.ServiceBinder.Intercept(...).Bind(new MyService()); // contract-first example, generated via protoc
79+
server.ServiceBinder.Intercept(...).AddCodeFirst(...); // code-first
5780
58-
[Usage examples are available in C#, VB and F#](https://github.com/protobuf-net/protobuf-net.Grpc/tree/main/examples/pb-net-grpc).
81+
// alternative for contract-first if not also using protobuf-net.Grpc, which provides the Bind API
82+
// YourService.BindService(server.ServiceBinder.Intercept(...), new MyService());
83+
```
5984

60-
## Anything else?
85+
## Other notes
6186

62-
`protobuf-net.Grpc` is created and maintained by [Marc Gravell](https://github.com/mgravell) ([@marcgravell](https://twitter.com/marcgravell)), the author of `protobuf-net`.
87+
It currently targets .NET Framework 4.7.2 up to .NET 6.0, using newer features when available. It is still very experimental - but most core things should work; feedback is welcome.
6388

64-
It makes use of tools from [grpc](https://github.com/grpc/), but is not official associated with, affiliated with, or endorsed by that project.
89+
Known gaps:
6590

66-
I look forward to your feedback, and if this could save you a ton of time, you're always welcome to [![Buy me a coffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/marcgravell)
91+
- gRPC auth (although transport auth works fine)
92+
- per-stream service activation (rather than singleton)
93+
- testing needs more coverage
94+
- per-stream backoff negotiation; designed, not yet implemented
95+
- for some reason the server implementation isn't working 100% with SAEA currently - hence `.AsStream().AsFrames()` instead of just `.AsFrames()`
96+
- open question around interceptor order

0 commit comments

Comments
 (0)