{"id":17453496,"url":"https://github.com/scalablecory/networktoolkit","last_synced_at":"2025-09-06T00:47:48.728Z","repository":{"id":80888776,"uuid":"310866275","full_name":"scalablecory/NetworkToolkit","owner":"scalablecory","description":"This project contains networking primitives for use with .NET.","archived":false,"fork":false,"pushed_at":"2021-02-13T09:11:18.000Z","size":418,"stargazers_count":95,"open_issues_count":2,"forks_count":4,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-08-01T04:56:51.875Z","etag":null,"topics":["http","networking","sockets"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scalablecory.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.TXT","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-11-07T14:48:51.000Z","updated_at":"2025-05-02T11:39:52.000Z","dependencies_parsed_at":null,"dependency_job_id":"c1213cb2-1c6c-4db5-a94e-55a5db21a01d","html_url":"https://github.com/scalablecory/NetworkToolkit","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/scalablecory/NetworkToolkit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scalablecory%2FNetworkToolkit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scalablecory%2FNetworkToolkit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scalablecory%2FNetworkToolkit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scalablecory%2FNetworkToolkit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scalablecory","download_url":"https://codeload.github.com/scalablecory/NetworkToolkit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scalablecory%2FNetworkToolkit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273842869,"owners_count":25177921,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-05T02:00:09.113Z","response_time":402,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["http","networking","sockets"],"created_at":"2024-10-18T00:43:00.068Z","updated_at":"2025-09-06T00:47:48.704Z","avatar_url":"https://github.com/scalablecory.png","language":"C#","readme":"# NetworkToolkit\n\nThis project contains networking primitives for use with .NET. It can be obtained from NuGet. [![Nuget](https://img.shields.io/nuget/v/NetworkToolkit)](https://www.nuget.org/packages/NetworkToolkit)\n\nThis is a bit of a prototyping playground right now and APIs will not be perfectly stable.\n\n## HTTP Primitives\n\nNetworkToolkit provides a lower-level HTTP client that prioritizes performance and flexibility. Once warmed up, it processes requests using zero allocations.\n\n### Performance\n\nIn the great majority of cases, `HttpClient` will be fast enough. Generally I/O will dominate a request's total time. However, if peak perf is needed, this library will be faster, especially as the number of headers in the request/response increase.\n\nBenchmarks are incomplete, so this should not be viewed as an exhaustive comparison:\n\n|            Method | RequestHeaders | ResponseBytes |      Mean |     Error |    StdDev |    Median | Ratio | RatioSD |\n|------------------ |--------------- |-------------- |----------:|----------:|----------:|----------:|------:|--------:|\n|         Primitive |        Minimal |       Minimal | 10.806 us | 0.3304 us | 0.9741 us | 10.985 us |  0.51 |    0.05 |\n| PrimitivePrepared |        Minimal |       Minimal |  9.278 us | 0.2091 us | 0.6066 us |  9.298 us |  0.44 |    0.04 |\n|    SocketsHandler |        Minimal |       Minimal | 21.323 us | 0.4380 us | 1.2136 us | 21.442 us |  1.00 |    0.00 |\n|                   |                |               |           |           |           |           |       |         |\n|         Primitive |        Minimal | StackOverflow | 13.665 us | 0.6509 us | 1.9089 us | 13.187 us |  0.16 |    0.02 |\n| PrimitivePrepared |        Minimal | StackOverflow | 14.108 us | 0.6328 us | 1.8559 us | 13.432 us |  0.17 |    0.03 |\n|    SocketsHandler |        Minimal | StackOverflow | 86.356 us | 1.7149 us | 4.2707 us | 87.476 us |  1.00 |    0.00 |\n|                   |                |               |           |           |           |           |       |         |\n|         Primitive |         Normal |       Minimal | 11.053 us | 0.2498 us | 0.7366 us | 11.149 us |  0.32 |    0.03 |\n| PrimitivePrepared |         Normal |       Minimal | 10.636 us | 0.2867 us | 0.8455 us | 10.701 us |  0.31 |    0.03 |\n|    SocketsHandler |         Normal |       Minimal | 34.775 us | 0.6940 us | 1.9231 us | 35.172 us |  1.00 |    0.00 |\n|                   |                |               |           |           |           |           |       |         |\n|         Primitive |         Normal | StackOverflow | 15.080 us | 0.6158 us | 1.7866 us | 14.874 us |  0.16 |    0.03 |\n| PrimitivePrepared |         Normal | StackOverflow | 13.964 us | 0.5963 us | 1.7490 us | 13.257 us |  0.15 |    0.02 |\n|    SocketsHandler |         Normal | StackOverflow | 94.221 us | 2.4801 us | 7.3127 us | 96.337 us |  1.00 |    0.00 |\n\n### A simple GET request using exactly one HTTP/1 connection, no pooling\n\nAvoid a connection pool to have exact control over connections.\n\n```c#\nawait using ConnectionFactory connectionFactory = new SocketConnectionFactory();\nawait using Connection connection = await connectionFactory.ConnectAsync(new DnsEndPoint(\"microsoft.com\", 80));\nawait using HttpConnection httpConnection = new Http1Connection(connection);\nawait using ValueHttpRequest request = (await httpConnection.CreateNewRequestAsync(HttpPrimitiveVersion.Version11, HttpVersionPolicy.RequestVersionExact)).Value;\n\nrequest.ConfigureRequest(contentLength: 0, hasTrailingHeaders: false);\nrequest.WriteRequest(HttpMethod.Get, new Uri(\"http://microsoft.com\"));\nrequest.WriteHeader(\"Accept\", \"text/html\");\nawait request.CompleteRequestAsync();\n\nawait request.ReadToFinalResponseAsync();\nConsole.WriteLine($\"Got response {request.StatusCode}.\");\n\nif(await request.ReadToHeadersAsync())\n{\n    await request.ReadHeadersAsync(...);\n}\n\nif(await request.ReadToContentAsync())\n{\n    int len;\n    byte[] buffer = ArrayPool\u003cbyte\u003e.Shared.Rent(4096);\n\n    do\n    {\n        while((len = await request.ReadContentAsync(buffer)) != 0)\n        {\n            ForwardData(buffer[..len]);\n        }\n    }\n    while(await request.ReadToNextContentAsync());\n\n    ArrayPool\u003cbyte\u003e.Shared.Return(buffer);\n}\n\nawait request.DrainAsync();\n```\n\n### Using the opt-in connection pool\n\nA single-host connection pool handles concurrent HTTP/1 requests, H2C upgrade, ALPN negotiation for HTTP/2, etc.\n\n```c#\nawait using ConnectionFactory connectionFactory = new SocketConnectionFactory();\nawait using HttpConnection httpConnection = new PooledHttpConnection(connectionFactory, new DnsEndPoint(\"microsoft.com\", 80), sslTargetHost: null);\nawait using ValueHttpRequest request = (await httpConnection.CreateNewRequestAsync(HttpPrimitiveVersion.Version11, HttpVersionPolicy.RequestVersionExact)).Value;\n```\n\n### Optimize frequently-used headers\n\nPrepare frequently-used headers to reduce CPU costs by pre-validating and caching protocol encoding. In the future, this will light up dynamic table compression in HTTP/2 and HTTP/3.\n\n```c#\nPreparedHeaderSet preparedHeaders = new PreparedHeaderSet()\n{\n    { \"User-Agent\", \"NetworkToolkit\" },\n    { \"Accept\", \"text/html\" }\n};\n\nawait using ValueHttpRequest request = ...;\n\nrequest.ConfigureRequest(contentLength: 0, hasTrailingHeaders: false);\nrequest.WriteRequest(HttpMethod.Get, new Uri(\"http://microsoft.com\"));\nrequest.WriteHeader(preparedHeaders);\n```\n\n### Avoiding strings\n\nAvoid `string` and `Uri` allocations, optimize away some related processing, and get tight control over encoding by passing in `ReadOnlySpan\u003cbyte\u003e`:\n\n```c#\nReadOnlySpan\u003cbyte\u003e method = HttpRequest.GetMethod; // \"GET\"\nReadOnlySpan\u003cbyte\u003e authority = ...; // \"microsoft.com:80\"\nReadOnlySpan\u003cbyte\u003e pathAndQuery = ...; // \"/\"\n\nReadOnlySpan\u003cbyte\u003e headerName = ...; // \"Accept\"\nReadOnlySpan\u003cbyte\u003e headerValue = ...; // \"text/html\"\n\nawait using ValueHttpRequest request = ...;\nrequest.ConfigureRequest(contentLength: 0, hasTrailingHeaders: false);\nrequest.WriteRequest(method, authority, pathAndQuery);\nrequest.WriteHeader(headerName, headerValue);\n```\n\n### Advanced processing\n\nAccess extensions like HTTP/2 ALT-SVC frames, or efficiently forward requests (reverse proxy) by processing requests as a loosely structured stream:\n\n```c#\nawait using ValueHttpRequest request = ...;\nwhile(await request.ReadAsync() != HttpReadType.EndOfStream)\n{\n    switch(request.ReadType)\n    {\n    case HttpReadType.InformationalResponse:\n        ProcessInformationalResponse(request.StatusCode, request.Version);\n        break;\n    case HttpReadType.FinalResponse:\n        ProcessResponse(request.StatusCode, request.Version);\n        break;\n    case HttpReadType.Headers:\n        await request.ReadHeadersAsync(...);\n        break;\n    case HttpReadType.Content:\n        int len;\n        byte[] buffer = ArrayPool\u003cbyte\u003e.Shared.Rent(4096);\n\n        while((len = await request.ReadContentAsync(buffer)) != 0)\n        {\n            ForwardData(buffer[..len]);\n        }\n\n        ArrayPool\u003cbyte\u003e.Shared.Return(buffer);\n        break;\n    case HttpReadType.TrailingHeaders:\n        await request.ReadHeadersAsync(...);\n        break;\n    case HttpReadType.AltSvc:\n        ProcessAltSvc(request.AltSvc);\n        break;\n    }\n}\n```\n\n## Connection Abstractions\n\nConnection abstractions used to abstract establishment of `Stream`-based connections.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscalablecory%2Fnetworktoolkit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscalablecory%2Fnetworktoolkit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscalablecory%2Fnetworktoolkit/lists"}