{"id":15014239,"url":"https://github.com/stratosblue/hoarwell","last_synced_at":"2026-01-16T20:28:06.628Z","repository":{"id":221121926,"uuid":"753514379","full_name":"stratosblue/Hoarwell","owner":"stratosblue","description":"a network application framework for rapid development of maintainable protocol servers and clients. 一个用于快速开发可维护的协议的服务器和客户端的网络应用程序框架。","archived":false,"fork":false,"pushed_at":"2024-04-27T13:46:21.000Z","size":167,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-16T18:03:14.797Z","etag":null,"topics":["client","dotnetty","netty","network","protocol","server","socket","tcp","udp"],"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/stratosblue.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-06T09:23:20.000Z","updated_at":"2024-04-27T13:44:55.000Z","dependencies_parsed_at":"2024-04-27T14:48:19.702Z","dependency_job_id":null,"html_url":"https://github.com/stratosblue/Hoarwell","commit_stats":{"total_commits":13,"total_committers":1,"mean_commits":13.0,"dds":0.0,"last_synced_commit":"ad4fb0891f29234fbc0b239da164cc7e6d74674b"},"previous_names":["stratosblue/hoarwell"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/stratosblue/Hoarwell","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stratosblue%2FHoarwell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stratosblue%2FHoarwell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stratosblue%2FHoarwell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stratosblue%2FHoarwell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stratosblue","download_url":"https://codeload.github.com/stratosblue/Hoarwell/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stratosblue%2FHoarwell/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":284807785,"owners_count":27066464,"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-11-17T02:00:06.431Z","response_time":55,"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":["client","dotnetty","netty","network","protocol","server","socket","tcp","udp"],"created_at":"2024-09-24T19:45:21.690Z","updated_at":"2025-11-17T02:01:47.564Z","avatar_url":"https://github.com/stratosblue.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"﻿# Hoarwell\n\na network application framework for rapid development of maintainable protocol servers and clients. 一个用于快速开发可维护的协议的服务器和客户端的网络应用程序框架。\n\n## 1. Intro\n\n基于抽象输入/输出实现的数据处理/通讯框架，旨在方便的在 `Socket` 等底层协议上进行基于二进制数据协议的通信及业务开发。\n\n### Features\n\n- 框架基于抽象的`Inputter`、`Outputter`，可以运行在任意可抽象的传输层之上，而不局限于`Socket`，例如：`NamedPipe`、`Http`等（参见示例项目 [ChatRoomOverHttp](./samples/ChatRoomOverHttp)）；\n- 基于 `管道` 的处理模型，可灵活组装、拓展；\n- `处理管道` 借鉴了部分 `Netty`/`DotNetty`，但与其不同：\n    - 入站(`Inbound`)与出站(`Outbound`)管道已拆分配置，不再混淆在一起配置；\n    - 入站(`Inbound`)管道实现为强类型流转，而非 `object`，数据流转更明确；\n- 框架当前只提供了部分保证基础运行的实现，如：帧头长度编码、解码等，未提供其它高层数据协议，如：`Http`、`gzip`等；\n- 框架依赖于 `DependencyInjection`，能更好的与相关生态集成；\n- 目标框架 `netstandard2.1`、`net8.0`；\n- 支持 `NativeAOT`；\n\n## 2. Design\n\n### 2.1 [名词列表](./docs/nouns.md)\n\n### 2.2 架构图\n\n![架构图](./docs/assets/architecture_diagram.svg)\n\n## 3. 如何使用\n\n### 3.1 Note：\n - 入站出站管道需要分别配置，总共需要配置四次，分别为 `服务端入站`、`服务端出站`、`客户端入站`、`客户端出站`，且编码解码管道顺序应对应，即：\n    - `客户端出站`编码管道对应`服务端入站`解码管道\n    - `客户端入站`解码管道对应`服务端出站`编码管道\n - 框架已提供保障基础运行的默认组件，配置过程中的各个组件都可以自行实现来替代默认实现\n\n### 引用包\n```xml\n\u003cItemGroup\u003e\n  \u003cPackageReference Include=\"Hoarwell\" Version=\"*-*\" /\u003e\n\n  \u003c!--基于 AspNetCore 的 SocketTransportFactory 的服务端实现--\u003e\n  \u003c!--\u003cPackageReference Include=\"Hoarwell.Transport.AspNetCore\" Version=\"*-*\" /\u003e--\u003e\n\u003c/ItemGroup\u003e\n```\n\n### 3.2 消息及消息处理器\n```C#\n//消息，使用默认的序列化器时需要实现接口：IBinaryParseable\u003cT\u003e, IBinarizable, ITypeIdentifierProvider\npublic class Message : IBinaryParseable\u003cMessage\u003e, IBinarizable, ITypeIdentifierProvider\n{\n    public static ReadOnlySpan\u003cbyte\u003e TypeIdentifier =\u003e //TODO 返回标识符数据例如 BitConverter.GetBytes(10001)\n\n    public static bool TryParse(in ReadOnlySequence\u003cbyte\u003e input, [MaybeNullWhen(false)] out Message result)\n    {\n        //TODO 实现反序列化逻辑\n    }\n\n    public void Serialize(in IBufferWriter\u003cbyte\u003e bufferWriter)\n    {\n        //TODO 实现序列化逻辑\n    }\n}\n\n//消息处理器，需要实现接口：IEndpointMessageHandler\u003cT\u003e\npublic class MessageHandler : IEndpointMessageHandler\u003cMessage\u003e\n{\n    public Task HandleAsync(IHoarwellContext context, Message? input)\n    {\n        //TODO 实现消息对应的业务逻辑\n    }\n}\n```\n\n-------\n\n### 3.3 服务端\n```C#\nservices.AddHoarwell(\"Server\")  //添加名为 Server 的应用程序\n        .UseDefaultApplication()    //使用默认应用程序\n        .UseAspNetCoreSocketTransportServer(options =\u003e options.EndPoints.Add(endPoint)) //使用AspNetCore的SocketTransportFactory服务端传输，并配置监听地址为 endPoint（注意此处与客户端不同）\n        .UseDefaultSerializer(serializerBuilder =\u003e  //使用默认的对象序列化器\n        {\n            //添加支持的序列化的消息类型\n            //TMessage 需要实现 IBinaryParseable\u003cTMessage\u003e 和 IBinarizable 接口\n            //serializerBuilder.AddMessage\u003cTMessage\u003e();\n        })\n        .UseDefaultTypeIdentifierAnalyzer(typeIdentifierAnalyzerBuilder =\u003e  //使用默认的类型标识符分析器\n        {\n            //添加支持的消息类型\n            //TMessage 需要实现 ITypeIdentifierProvider 接口\n            //typeIdentifierAnalyzerBuilder.AddMessage\u003cTMessage\u003e();\n        })\n        .ConfigureInboundPipeline(pipelineBuilder =\u003e    //配置入站管道\n        {\n            //配置入站处理管道\n            pipelineBuilder.UseUInt32LengthFieldBasedFrameDecoder() //使用基于 uint 的长度帧头解码器中间件\n                           .UseDefaultMessageDeserializer() //使用默认的消息序列化中间件\n                           .RunEndpoint(endpointBuilder =\u003e  //配置入站终结点\n                           {\n                                //添加消息的处理器\n                                //TMessage 需要已在 Serializer 配置支持\n                                //TMessageHandler 需要实现 IEndpointMessageHandler\u003cTMessage\u003e 接口\n                                //endpointBuilder.Handle\u003cTMessage, TMessageHandler\u003e();\n                           });\n        })\n        .ConfigureOutboundPipeline(pipelineBuilder =\u003e   //配置出站管道\n        {\n            //配置出站处理管道\n            pipelineBuilder.UseUInt32LengthFieldBasedFrameEncoder() //使用基于 uint 的长度帧头解码器中间件\n                           .RunDefaultMessageSerializer();  //运行默认的消息序列化出站终结点\n        });\n\nawait using var serviceProvider = services.BuildServiceProvider();\nawait using var applicationRunner = serviceProvider.GetRequiredKeyedService\u003cIHoarwellApplicationRunner\u003e(\"Server\");  //从 DI 容器中获取名为 Server 的应用程序运行器\n\nawait applicationRunner.StartAsync();   //运行应用程序\n```\n\n-------\n\n### 3.4 客户端\n```C#\nservices.AddHoarwell(\"Client\")  //添加名为 Client 的应用程序\n        .UseDefaultApplication()    //使用默认应用程序\n        .UseDefaultSocketTransportClient(options =\u003e options.EndPoints.Add(endPoint))    //使用默认的基于Socket的客户端传输，并配置远程地址为 endPoint（注意此处与服务端不同）\n        .UseDefaultSerializer(serializerBuilder =\u003e  //使用默认的对象序列化器\n        {\n            //添加支持的序列化的消息类型\n            //TMessage 需要实现 IBinaryParseable\u003cTMessage\u003e 和 IBinarizable 接口\n            //serializerBuilder.AddMessage\u003cTMessage\u003e();\n        })\n        .UseDefaultTypeIdentifierAnalyzer(typeIdentifierAnalyzerBuilder =\u003e  //使用默认的类型标识符分析器\n        {\n            //添加支持的消息类型\n            //TMessage 需要实现 ITypeIdentifierProvider 接口\n            //typeIdentifierAnalyzerBuilder.AddMessage\u003cTMessage\u003e();\n        })\n        .ConfigureInboundPipeline(pipelineBuilder =\u003e    //配置入站管道\n        {\n            //配置入站处理管道\n            pipelineBuilder.UseUInt32LengthFieldBasedFrameDecoder() //使用基于 uint 的长度帧头解码器中间件\n                           .UseDefaultMessageDeserializer() //使用默认的消息序列化中间件\n                           .RunEndpoint(endpointBuilder =\u003e  //配置入站终结点\n                           {\n                                //添加消息的处理器\n                                //TMessage 需要已在 Serializer 配置支持\n                                //TMessageHandler 需要实现 IEndpointMessageHandler\u003cTMessage\u003e 接口\n                                //endpointBuilder.Handle\u003cTMessage, TMessageHandler\u003e();\n                           });\n        })\n        .ConfigureOutboundPipeline(pipelineBuilder =\u003e   //配置出站管道\n        {\n            //配置出站处理管道\n            pipelineBuilder.UseUInt32LengthFieldBasedFrameEncoder() //使用基于 uint 的长度帧头解码器中间件\n                           .RunDefaultMessageSerializer();  //运行默认的消息序列化出站终结点\n        });\n\nawait using var serviceProvider = services.BuildServiceProvider();\nawait using var applicationRunner = serviceProvider.GetRequiredKeyedService\u003cIHoarwellApplicationRunner\u003e(\"Client\");  //从 DI 容器中获取名为 Client 的应用程序运行器\n\nusing var contextWaiter = applicationRunner.GetContextWaiter(); //获取客户端上下文等待器\n\nawait applicationRunner.StartAsync();   //启动应用程序\n\nvar context = await contextWaiter.Task; //获取客户端上下文\n\n// 使用获取到的 context 进行交互\n```\n\n-------\n\n#### 更多信息参见示例代码\n\n-------\n\n## 4. Samples\n\n - [ChatRoom](./samples/ChatRoom): 简单的聊天室实现\n - [ChatRoomOverHttp](./samples/ChatRoomOverHttp): 简单的聊天室实现，并运行于 `Http` 协议之上\n\n## 5. Benchmark\n\n[Benchmark](./benchmark)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstratosblue%2Fhoarwell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstratosblue%2Fhoarwell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstratosblue%2Fhoarwell/lists"}