.net GRPC服务搭建,跨进程调用。C#应用和Python应用之间的通信。

发布于:2025-04-03 ⋅ 阅读:(18) ⋅ 点赞:(0)

1.理解GRPC

GRPC本质上是通过谷歌开源的protobuff标准协议实现的传输,和http那种类似,但是他更高效,因为他底层数据是通过二进制传输,比传统的json快很多,通常用于直播间的推流送流。

2.为什么用GRPC

最开始只想解决跨进程通信,用传统的MQ就可以实现,但是GRPC近些年也越来越火了,就试了试。因为他更标准,兼容性更好,可以跨语言跨脚本使用,大家按照他的标准去定义调用就好了。

3.C#应用和Python应用如何通过GRPC互相调用

在这里我C#应用做为GRPC的服务端。Python应用作为客户端去调用。

3.1首先定义标准.proto文件

syntax = "proto3";

option csharp_namespace = "DY_service";

package DY_serviceservice;

// 定义服务
service Calculator {
  rpc Get_result (AddRequest) returns (AddResponse);
}

// 请求消息,包含两个参数
message AddRequest {
  string fullUrl = 1;
  string method = 2;
}

// 响应消息
message AddResponse {
  string result = 1;
}

3.2文件字段解释

  • syntax = "proto3"; // 使用 Protocol Buffers 第3版语法
  • option csharp_namespace = "DY_service"; // 生成的C#代码的命名空间
  • package DY_serviceservice; // 包名(防止命名冲突)
  • Calculator: 服务名称,客户端通过它调用方法。
  • Get_result: 远程方法名,用于计算 。
  • AddRequest: 输入参数类型。
  • AddResponse: 返回结果类型。

3.3搭建C#服务端

3.3.1.创建WinForms项目
  • 使用Visual Studio新建一个Windows Forms App (.NET Framework) 项目(确保选择.NET
    Core 3.1或更高版本,建议使用.NET 6+)。
3.3.2添加NuGet包
  • 在项目中安装以下NuGet包:
  • Grpc.AspNetCore (包含服务器和客户端库)
  • Google.Protobuf (ProtoBuf消息处理)
  • Grpc.Tools (代码生成工具)
3.3.3添加.proto文件
  • 在项目中添加3.1的proto文件
3.3.4配置.proto文件生成
  • 右键.proto文件 → 属性 → 设置:

  • 生成操作:Protobuf compiler

  • gRPC Stub Classes:Server only

3.3.5实现gRPC服务

创建类CalculatorService.cs:

using DY_service;
using Grpc.Core;
using Microsoft.Extensions.Logging;

namespace DY
{
    public class CalculatorService : Calculator.CalculatorBase
    {
        private readonly ILogger<CalculatorService> _logger;

        public CalculatorService(ILogger<CalculatorService> logger)
        {
            _logger = logger;
        }

        public override async Task<AddResponse> Get_a_bogus(AddRequest request, ServerCallContext context)
        {


            try
            {
                // 直接 await 异步调用,无需 Task.Run
                string result = await Form1.CallJavaScriptFunction(request.FullUrl, request.Method);
                return new AddResponse { Result = result };
            }
            catch (Exception ex)
            {
                // 记录错误并返回空响应(或自定义错误响应)
                Console.WriteLine($"gRPC 调用失败: {ex.Message}");
                return new AddResponse { Result = "ERROR: " + ex.Message };
            }
        }
    }
}

这里的Get_a_bogus方法就是你标准中定义的方法DY_service是标准中的命名空间。然后还有定义的参数,都是和标准文件中一样。

4. 启动gRPC服务器

在Form1的代码中(例如窗体加载事件):

  private IHost _grpcHost;
  private void Form1_Load(object sender, EventArgs e)
  {
      _grpcHost = Host.CreateDefaultBuilder()
 .ConfigureWebHostDefaults(webBuilder =>
 {
     webBuilder.UseStartup<Startup>();
     webBuilder.UseUrls("http://localhost:5000");
     // Program.cs
     webBuilder.ConfigureKestrel(options =>
     {
         options.ListenLocalhost(5000, o => o.Protocols = HttpProtocols.Http2);
     });
 })
 .Build();

      Task.Run(() => _grpcHost.Start()); // 在后台线程启动
  }



  private async void Form1_FormClosed(object sender, FormClosedEventArgs e)
  {


      if (_grpcHost != null)
      {
          try
          {
              // 最多等待 3 秒
              await _grpcHost.StopAsync(TimeSpan.FromSeconds(3));
          }
          catch (Exception ex)
          {
              Debug.WriteLine($"gRPC 服务器停止失败: {ex.Message}");
          }
          finally
          {
              _grpcHost.Dispose();
              _grpcHost = null; // 防止重复释放
          }
      }

      //this.Close(); // 关闭窗口
      //Application.Exit(); // 结束进程
  }

添加Startup.cs类:

using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;

namespace DY
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddGrpc();
        }

        public void Configure(IApplicationBuilder app)
        {

            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGrpcService<CalculatorService>();
            });
        }
    }
}

然后运行程序,GRPC服务就启动了。具体的代码意思自己参考官方文档。

5.Python客户端测试代码

  • 安装grpc包
pip install grpcio grpcio-tools

把定义好的 .proto 文件复制到py客户端项目根目录执行如下命令

python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. DY__service.proto

只需要把DY_service.proto改成你自己的文件名就行了,然后会生成2个文件。_pb2.py_pb2_grpc.py这2文件中的代码不要改,直接调用就行。

import grpc
import DY_service_pb2
import DY_service_pb2_grpc

def run():
    channel = grpc.insecure_channel('localhost:5000')
    stub = DY_service_pb2_grpc.CalculatorStub(channel)
    
    response = stub.Get_resut(DY_service_pb2.AddRequest(fullUrl="https://www.dy.com", method="GET"))
    print(f"结果: {response.result}")  # 应该输出 结果

if __name__ == '__main__':
    run()

这样就可以实现基础通信了 直接调用远程方法,总体还是挺方便。


网站公告

今日签到

点亮在社区的每一天
去签到