第四章 RPC 調用

来源:https://www.cnblogs.com/xuyubing/archive/2023/12/18/17910922.html
-Advertisement-
Play Games

通過以上案例我們發現,Http請求調用服務實例屬實過於麻煩。其實對於請求同一個服務,很多步驟都是相同的,例如:服務名,地址,httpClient 創建步驟等。 RPC的出現,就是為瞭解決這一問題。 RPC: 即我們常說的遠程過程調用,就是像調用本地方法一樣調用遠程方法,通信協議大多採用二進位方式。 ...


通過以上案例我們發現,Http請求調用服務實例屬實過於麻煩。其實對於請求同一個服務,很多步驟都是相同的,例如:服務名,地址,httpClient 創建步驟等。

RPC的出現,就是為瞭解決這一問題。

RPC: 即我們常說的遠程過程調用,就是像調用本地方法一樣調用遠程方法,通信協議大多採用二進位方式。

常用的RPC框架有(標粗的是準備講解的):

  • gRPC

    gRPC是一個現代的開源高性能遠程過程調用(RPC)框架,可以在任何環境中運行。它可以有效地連接數據中心內和跨數據中心的服務,支持負載均衡、跟蹤、健康檢查和身份驗證。它也適用於分散式計算,將設備、移動應用程式和瀏覽器連接到後端服務---這是官方給的說明

  • openFeign

    簡化HttpClient調用過程,讓net core開發變得更簡單。

  • Thrift

    Thrift是一種介面描述語言和二進位通訊協議,它被用來定義和創建跨語言的服務。它被當作一個遠程過程調用(RPC)框架來使用,是由Facebook為“大規模跨語言服務開發”而開發的。它通過一個代碼生成引擎聯合了一個軟體棧,來創建不同程度的、無縫的跨平臺高效服務,可以使用C#、C++、Cappuccino、Cocoa、Delphi、Erlang、Go、Haskell、Java、Node.js、OCaml、Perl、PHP、Python、Ruby和Smalltalk。

  • Shuttler.net

    Shuttler.Net是一個高性能分散式框架,如果你在使用老去的remoting,webservices分散式架構,或在使用新生的wcf,那麼你也可以嘗試下Shuttler.Net。 如果你想開發自己的IM服務端和客戶端(或游戲大廳),你也可以使用Shuttler.Net,只需你制定報文協議即可,其他傳輸層Shuttler幫你搞定。Shuttler.Net核心組件Artery正如她的名字一樣:脈,基於Tcp的應用棧,可以幫你傳輸任何能量,使你想唱就唱。

    主要功能點包括:

    1. 分散式RPC,目前支持Tcp和Http(類REST風格)雙通道(見Demo:TcpRpcTest和HttpRpcTest): 可以多個RpcServer端和多個RpcClient端,其中client通過HashingAlgorithm根據Key計算出server。

    2. 分散式緩存系統(Memcached),包括MemcachedServer和MemcachedClient(見Demo:MemcachedTest): 可以多個MemcachedServer端和多個MemcachedClient端,其中client通過HashingAlgorithm根據Key計算出server。

    3. IM協議棧,使用Shuttler.Net的Artery組件可以輕鬆實現一個IMServer端和IMClient端(見Demo:IMTest): IMTest中實現IM的登錄密碼校驗,通訊協議自己定義即可,協議Demo見Shuttler_Artery_Protocol。

 

1. gRPC 詳細教程

官網:https://grpc.io

gRPC 是一種與語言無關的高性能遠程過程調用 (RPC) 框架。

gRPC 的主要優點是:

  • 現代高性能輕量級 RPC 框架。

  • 協定優先 API 開發,預設使用協議緩衝區,允許與語言無關的實現。

  • 可用於多種語言的工具,以生成強類型伺服器和客戶端。

  • 支持客戶端、伺服器和雙向流式處理調用。

  • 使用 Protobuf 二進位序列化減少對網路的使用。

這些優點使 gRPC 適用於:

  • 效率至關重要的輕量級微服務。

  • 需要多種語言用於開發的 Polyglot 系統。

  • 需要處理流式處理請求或響應的點對點實時服務。

警告

若要將 ASP.NET Core gRPC用於 Azure 應用服務或 IIS,則該 gRPC 具有額外的要求。 有關可以在何處使用 gRPC 的詳細信息,請參閱 .NET 支持的平臺上的 gRPC

 

1. 快速入門

本教程演示瞭如何創建 .NET Core gRPC客戶端和 ASP.NET Core gRPC 伺服器。 最後會生成與 gRPC Greeter 服務進行通信的 gRPC 客戶端。

在本教程中,你將瞭解:

  • 創建 gRPC 伺服器。

  • 創建 gRPC 客戶端。

  • 使用 gRPC Greeter 服務測試 gRPC 客戶端。

 

創建gRPC服務

  • 啟動 Visual Studio 2022 並選擇“創建新項目”。

  • 在“創建新項目”對話框中,搜索 gRPC。 選擇“ASP.NET Core gRPC 服務”,並選擇“下一步” 。

  • 在“配置新項目”對話框中,為“項目名稱”輸入 GrpcGreeter。 將項目命名為“GrpcGreeter”非常重要,這樣在複製和粘貼代碼時命名空間就會匹配。

  • 選擇“下一頁”。

  • 在“其他信息”對話框中,選擇“.NET 6.0 (長期支持)”,然後選擇“創建。

 

項目文件

GrpcGreeter 項目文件:

  • Protos/greet.proto

    .proto 文件中定義服務和消息

  • Services 文件夾:包含 Greeter 服務的實現。

  • appSettings.json:包含配置數據,如 Kestrel 使用的協議。

  • Program.cs,其中包含:
    • gRPC 服務的入口點。

    • 配置應用行為的代碼。

 

創建gRPC 控制台客戶端

  • 打開 Visual Studio 的第二個實例並選擇“創建新項目”。

  • 在“創建新項目”對話框中,選擇“控制台應用程式”,然後選擇“下一步” 。

  • 在“項目名稱”文本框中,輸入“GrpcGreeterClient”,然後選擇“下一步” 。

  • 在“其他信息”對話框中,選擇“.NET 6.0 (長期支持)”,然後選擇“創建”。

需要安裝的包

Grpc.Net.Client 2.50.0
Google.Protobuf 3.22.0
Grpc.Tools 2.50.0

 

添加 proto文件

  • 在 gRPC 客戶端項目中創建 Protos 文件夾。

  • 從 gRPC Greeter 服務將 Protos\greet.proto 文件複製到 gRPC 客戶端項目中的 Protos 文件夾 。

  • greet.proto 文件中的命名空間更新為項目的命名空間:

    option csharp_namespace = "GrpcGreeterClient";

     

  • 編輯 GrpcGreeterClient.csproj 項目文件:

  • 添加具有引用 greet.proto 文件的 <Protobuf> 元素的項組:

    <ItemGroup>
      <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
    </ItemGroup>

     

 

創建 Greeter 客戶端

  • 構建客戶端項目,用於在 GrpcGreeterClient 命名空間中創建類型。

GrpcGreeterClient 類型是由生成進程自動生成的。 工具包 Grpc.Tools 基於 greet.proto 文件生成以下文件:

  • GrpcGreeterClient\obj\Debug\[TARGET_FRAMEWORK]\Protos\Greet.cs:用於填充、序列化和檢索請求和響應消息類型的協議緩衝區代碼。

  • GrpcGreeterClient\obj\Debug\[TARGET_FRAMEWORK]\Protos\GreetGrpc.cs:包含生成的客戶端類。

  • 使用以下代碼更新 gRPC 客戶端 Program.cs 文件。

    using System.Threading.Tasks;
    using Grpc.Net.Client;
    using GrpcGreeterClient;
    
    // 服務端的地址
    using var channel = GrpcChannel.ForAddress("https://localhost:7042");
    var client = new Greeter.GreeterClient(channel);
    var reply = await client.SayHelloAsync(
                      new HelloRequest { Name = "GreeterClient" });
    Console.WriteLine("Greeting: " + reply.Message);
    Console.WriteLine("Press any key to exit...");
    Console.ReadKey();

     

    本文中的代碼需要 ASP.NET Core HTTPS 開發證書來保護 gRPC 服務。 如果 .NET gRPC 客戶端失敗並顯示消息 The remote certificate is invalid according to the validation procedure.The SSL connection could not be established.,則開發證書不受信任。 要解決此問題,請參閱使用不受信任/無效的證書調用 gRPC 服務

 

2. proto 文件

gRPC 使用協定優先方法進行 API 開發。 預設情況下,協議緩衝區 (protobuf) 用作介面定義語言 (IDL)。 .proto 文件包含:

  • gRPC 服務的定義。

  • 在客戶端與伺服器之間發送的消息。

 

 

.proto 添加到 C# 應用

通過將 .proto 文件添加到 <Protobuf> 項組中,可將該文件包含在項目中:

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

 

預設情況下,<Protobuf> 引用將生成具體的客戶端和服務基類。 可使用引用元素的 GrpcServices 特性來限制 C# 資產生成。 有效 GrpcServices 選項如下:

Proto GrpcServices 選項

  • Both(如果不存在,則為預設值)

  • Server

  • Client

  • None

 

.proto 工具支持

需要工具包 Grpc.Tools 才能從 .proto 文件生成 C# 資產。 生成的資產(文件):

  • 在每次生成項目時按需生成。

  • 不會添加到項目中或是簽入到源代碼管理中。

  • 是包含在 obj 目錄中的生成工件。

伺服器和客戶端項目都需要此包。 Grpc.AspNetCore 元包中包含對 Grpc.Tools 的引用。 伺服器項目可以使用 Visual Studio 中的包管理器或通過將 <PackageReference> 添加到項目文件來添加 Grpc.AspNetCore

<PackageReference Include="Grpc.AspNetCore" Version="2.40.0" />

 

客戶端項目應直接引用 Grpc.Tools 以及使用 gRPC 客戶端所需的其他包。 運行時不需要工具包,因此依賴項標記為 PrivateAssets="All"

<PackageReference Include="Google.Protobuf" Version="3.18.0" />
<PackageReference Include="Grpc.Net.Client" Version="2.40.0" />
<PackageReference Include="Grpc.Tools" Version="2.40.0">
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
  <PrivateAssets>all</PrivateAssets>
</PackageReference>

 

生成的 C# 代碼

工具包會生成表示在所包含 .proto 文件中定義的消息的 C# 類型。

對於伺服器端資產,會生成抽象服務基類型。 基類型包含 .proto 文件中所含的所有 gRPC 調用的定義。 創建一個派生自此基類型併為 gRPC 調用實現邏輯的具體服務實現。 對於 greet.proto(前面所述的示例),會生成一個包含虛擬 SayHello 方法的抽象 GreeterBase 類型。 具體實現 GreeterService 會替代該方法,並實現處理 gRPC 調用的邏輯。

public class GreeterService : Greeter.GreeterBase
{
    private readonly ILogger<GreeterService> _logger;
    public GreeterService(ILogger<GreeterService> logger)
    {
        _logger = logger;
    }

    public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
    {
        return Task.FromResult(new HelloReply
        {
            Message = "Hello " + request.Name
        });
    }
}

 

對於客戶端資產,會生成一個具體客戶端類型。 .proto 文件中的 gRPC 調用會轉換為具體類型中的方法,可以進行調用。 對於 greet.proto(前面所述的示例),會生成一個 GreeterClient 類型。 調用 GreeterClient.SayHelloAsync 以發起對伺服器的 gRPC 調用。

// 埠號必須與gRPC 服務的埠一致
using var channel = GrpcChannel.ForAddress("https://localhost:7042");
var client = new Greeter.GreeterClient(channel);
var reply = await client.SayHelloAsync(
                  new HelloRequest { Name = "GreeterClient" });
Console.WriteLine("Greeting: " + reply.Message);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();

 

預設情況下,會為 <Protobuf> 項組中包含的每個 .proto 文件都生成伺服器和客戶端資產。 若要確保伺服器項目中僅生成伺服器資產,請將 GrpcServices 屬性設置為 Server

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
</ItemGroup>

 

同樣,該屬性在客戶端項目中設置為 Client

<ItemGroup>
  <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
</ItemGroup>

 

 

3. ProtoBuf Message

消息是 Protobuf 中的主要數據傳輸對象, 它們在概念上類似於 .NET 類.

syntax = "proto3";

option csharp_namespace = "Contoso.Messages";

message Person {
    int32 id = 1;
    string first_name = 2 // FirstName
    string last_name = 3;
}

 

前面的消息定義將三個欄位指定為名稱/值對。 與 .NET 類型上的屬性類似,每個欄位都有名稱和類型。 欄位類型可以是 Protobuf 標量值類型(如 int32),也可以是其他消息。

Protobuf 樣式命名風格 建議使用 underscore_separated_names 作為欄位名稱。 為 .NET 應用創建的新 Protobuf 消息應遵循 Protobuf 樣式準則。 .NET 工具會自動生成使用 .NET 命名標準的 .NET 類型。 例如,first_name Protobuf 欄位生成 FirstName .NET 屬性。

包括名稱,消息定義中的每個欄位都有一個唯一的編號。 消息序列化為 Protobuf 時,欄位編號用於標識欄位。 序列化一個小編號比序列化整個欄位名稱要快。 因為欄位編號標識欄位,所以在更改編號時務必小心。

生成應用時,Protobuf 工具將從 .proto 文件生成 .NET 類型。 Person 消息生成 .NET 類:

public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

 

標量值類型

Protobuf 支持一系列本機標量值類型。 下表列出了全部本機標量值類型及其等效 C# 類型:

Protobuf 類型C# 類型
double double
float float
int32 int
int64 long
uint32 uint
uint64 ulong
sint32 int
sint64 long
fixed32 uint
fixed64 ulong
sfixed32 int
sfixed64 long
bool bool
string string
bytes ByteString

標量值始終具有預設值,並且該預設值不能設置為 null。 此約束包括 stringByteString,它們都屬於 C# 類。 string 預設為空字元串值,ByteString 預設為空位元組值。 嘗試將它們設置為 null 會引發錯誤。

日期和時間

本機標量類型不提供與 .NET 的 DateTimeOffsetDateTimeTimeSpan 等效的日期和時間值。 可使用 Protobuf 的一些“已知類型”擴展來指定這些類型。 這些擴展為受支持平臺中的複雜欄位類型提供代碼生成和運行時支持。

下表顯示日期和時間類型:

.NET 類型Protobuf 已知類型
DateTimeOffset google.protobuf.Timestamp
DateTime google.protobuf.Timestamp
TimeSpan google.protobuf.Duration
syntax = "proto3";

import "google/protobuf/duration.proto";  
import "google/protobuf/timestamp.proto";

message Meeting {
    string subject = 1;
    google.protobuf.Timestamp start = 2;
    google.protobuf.Duration duration = 3;
}  

 

C# 類中生成的屬性不是 .NET 日期和時間類型。 屬性使用 Google.Protobuf.WellKnownTypes 命名空間中的 TimestampDuration 類。 這些類提供在 DateTimeOffsetDateTimeTimeSpan 之間進行轉換的方法。



Meeting meeting = new Meeting()
{
    Start = DateTime.Now.ToTimestamp(),
    Duration = Duration.FromTimeSpan(TimeSpan.FromDays(1))
};

DateTime startTime = meeting.Start.ToDateTime();
DateTimeOffset time = meeting.Start.ToDateTimeOffset();
TimeSpan? duration = meeting.Duration?.ToTimeSpan();

 

備註

Timestamp 類型適用於 UTC 時間。 DateTimeOffset 值的偏移量始終為零,並且 DateTime.Kind 屬性始終為 DateTimeKind.Utc

可為 null 的類型

C# 的 Protobuf 代碼生成使用本機類型,如 int 表示 int32。 因此這些值始終包括在內,不能為 null

對於需要顯式 null 的值(例如在 C# 代碼中使用 int?),Protobuf 的“已知類型”包括編譯為可以為 null 的 C# 類型的包裝器。 若要使用它們,請將 wrappers.proto 導入到 .proto 文件中,如以下代碼所示:

syntax = "proto3";

import "google/protobuf/wrappers.proto";

message Person {
    // ...
    google.protobuf.Int32Value age = 5;
}

 

wrappers.proto 類型不會在生成的屬性中公開。 Protobuf 會自動將它們映射到 C# 消息中相應的可為 null 的 .NET 類型。 例如,google.protobuf.Int32Value 欄位生成 int? 屬性。 引用類型屬性(如 stringByteString )保持不變,但可以向它們分配 null,這不會引發錯誤。

下表完整列出了包裝器類型以及它們的等效 C# 類型:

C# 類型已知類型包裝器
bool? google.protobuf.BoolValue
double? google.protobuf.DoubleValue
float? google.protobuf.FloatValue
int? google.protobuf.Int32Value
long? google.protobuf.Int64Value
uint? google.protobuf.UInt32Value
ulong? google.protobuf.UInt64Value
string google.protobuf.StringValue
ByteString google.protobuf.BytesValue

 

位元組

Protobuf 支持標量值類型為 bytes 的二進位有效負載。 C# 中生成的屬性使用 ByteString 作為屬性類型。

使用 ByteString.CopyFrom(byte[] data) 從位元組數組創建新實例:

var data = await File.ReadAllBytesAsync(path);

var payload = new PayloadResponse();
payload.Data = ByteString.CopyFrom(data);

 

使用 ByteString.SpanByteString.Memory 直接訪問 ByteString 數據。 或調用 ByteString.ToByteArray() 將實例轉換回位元組數組:

var payload = await client.GetPayload(new PayloadRequest());

await File.WriteAllBytesAsync(path, payload.Data.ToByteArray());

 

集合

列表

Protobuf 中,在欄位上使用 repeated 首碼關鍵字指定列表。 以下示例演示如何創建列表:

message Person {
    // ...
    repeated string roles = 8;
}

 

在生成的代碼中,repeated 欄位由 Google.Protobuf.Collections.RepeatedField<T> 泛型類型表示。

public class Person
{
    // ...
    public RepeatedField<string> Roles { get; }
}

 

RepeatedField<T> 實現了 IList。 因此你可使用 LINQ 查詢,或者將其轉換為數組或列表。 RepeatedField<T> 屬性沒有公共 setter。 項應添加到現有集合中。

var person = new Person();

person.Roles.Add("user");

var roles = new [] { "admin", "manager" };
person.Roles.Add(roles);

var list = roles.ToList();

 

 

字典

.NET IDictionary 類型在 Protobuf 中使用 map<key_type, value_type> 表示。

ProtoBuf複製

message Person {
    // ...
    map<string, string> attributes = 9;
}

 

在生成的 .NET 代碼中,map 欄位由 Google.Protobuf.Collections.MapField<TKey, TValue> 泛型類型表示。 MapField<TKey, TValue> 實現了 IDictionary。 與 repeated 屬性一樣,map 屬性沒有公共 setter。 項應添加到現有集合中。

var person = new Person();

// 添加一項
person.Attributes["created_by"] = "James";

// 添加多項
var attributes = new Dictionary<string, string>
{
    ["last_modified"] = DateTime.UtcNow.ToString()
};
person.Attributes.Add(attributes);

 

 

 

 

 

4. 創建 gRPC 服務和方法

本文檔介紹如何以 C# 創建 gRPC 服務和方法。 包括:

  • 如何在 .proto 文件中定義服務和方法。

  • 使用 gRPC C# 工具生成的代碼。

  • 實現 gRPC 服務和方法。

 

創建新的 gRPC 服務

設置appsetting.json
"Kestrel": {
    "EndpointDefaults": {
      "Protocols": "Http2"
    }
  }

 

或者Program.cs 中配置如下代碼:

// Gprc 需要 Http2.0
builder.WebHost.UseKestrel(p =>
{
    p.ConfigureEndpointDefaults(opt =>
    {
        opt.Protocols = HttpProtocols.Http2;
    });
});
 

 

引用包:

Grpc.AspNetCore  2.50.0

 

 

服務和消息是在 .proto 文件中定義的。 然後,C# 工具從 .proto 文件生成代碼。 對於伺服器端資產,將為每個服務生成一個抽象基類型,同時為所有消息生成類。

以下 .proto 文件:

  • 定義 Greeter 服務。

  • Greeter 服務定義 SayHello 調用。

  • SayHello 發送 HelloRequest 消息並接收 HelloReply 消息

syntax = "proto3";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

 

C# 工具生成 C# GreeterBase 基類型:

public abstract partial class GreeterBase
{
    public virtual Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
    {
        throw new RpcException(new Status(StatusCode.Unimplemented, ""));
    }
}

public class HelloRequest
{
    public string Name { get; set; }
}

public class HelloReply
{
    public string Message { get; set; }
}

 

預設情況下,生成的 GreeterBase 不執行任何操作。 它的虛擬 SayHe

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、要求 1.設計並驗證如下演算法:圖採用鄰接矩陣表示,實現無向圖的深度優先搜索與有向圖的廣度優先搜索。 2.設計並驗證如下演算法:帶權圖採用鄰接表表示,實現無向圖的廣度優先搜索與有向圖的深度優先搜索。 二、代碼 1. #include<stdio.h> #include<stdlib.h> #incl ...
  • 數據的預處理是數據分析,或者機器學習訓練前的重要步驟。通過數據預處理,可以 提高數據質量,處理數據的缺失值、異常值和重覆值等問題,增加數據的準確性和可靠性 整合不同數據,數據的來源和結構可能多種多樣,分析和訓練前要整合成一個數據集 提高數據性能,對數據的值進行變換,規約等(比如無量綱化),讓演算法更加 ...
  • `QListWidget` 是 Qt 中的一個列表框組件,用於顯示一列項目,並允許用戶進行選擇。每個項目可以包含一個圖標和文本,可以使用 `QListWidgetItem` 類來表示。`ListWidget`組件與`TreeWidget`有些相似,區別在於`TreeWidget`可以實現嵌套以及多字... ...
  • WebAPI部署到IIS 1 開啟IIS功能 控制面板->程式->程式和功能->啟用或關閉Windows功能,以下打勾: 2 下載對應版本的dotNet Core 本文為ASP .NET Core6.0版本,需下載對應6.0版本的運行時,下載地址:https://dotnet.microsoft.c ...
  • 1. 簡單需求 通過圖文識別讀取一個指定window視窗的文本。 獲取視窗句柄,截圖保存成bitmap ,調用圖文識別庫. 測試結果是對中文下的識別不是特別好。 需要註意的是,tessdata要下載指定目錄頁下。 2. 引用包 a. 引用 tesseract4.1 b. Emgu.CV組件 3. 上 ...
  • 前言 本人最近在社區里說想做稚暉君的那個瀚文鍵盤來著,結果遇到兩個老哥一個老哥送了我電路板,一個送了我焊接好元件的電路板,既然大家這麼捨得,那我也就真的投入製作了這把客制化鍵盤,當然我為了省錢也是特意把外殼模型重新切割,用3D印表機列印了整個外殼,不得不說省了八九百的CNC費用。鍵盤介紹我就不說了, ...
  • 1. 常見的數據結構 1. 棧(stack) 特點:先進後出,後進先出 2. 隊列(Queue) 特點:先進先出 3. 數組(Array) 查詢速度快:通過地址值與索引可快速定位到數據 刪除效率低:刪除數據後,要將每個數據前移 添加效率極低:添加位置後,每個數據都後移,再添加數據。 4. 鏈表 鏈接 ...
  • c# 更改快捷方式文件圖標c# 更改快捷方式文件圖標c# 更改快捷方式文件圖標c# 更改快捷方式文件圖標c# 更改快捷方式文件圖標c# 更改快捷方式文件圖標c# 更改快捷方式文件圖標c# 更改快捷方式文件圖標c# 更改快捷方式文件圖標 /// <summary> /// 更改快捷方式文件圖標 /// ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...