在 Unix 套接字上使用 Flutter gRPC

问题描述 投票:0回答:1

我是 Flutter 的新手,想通过 gRPC 在前面使用 Flutter 并在后面使用 Go 创建一个简单的应用程序。我决定使用 Unix 套接字 (UDS) 而不是 TCP。当服务器和客户端都在 Go 中时使用 UDS 工作正常。但是,当尝试使用 Flutter over UDS 创建 gRPC 客户端时,出现以下错误。

[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: gRPC Err
or (code: 14, codeName: UNAVAILABLE, message: Error connecting: SocketException:
 Failed host lookup: 'unix:///tmp/test.socket' (OS Error: Name or service not kn
own, errno = -2), details: null, rawResponse: null, trailers: {})

我试着寻找类似的问题。据我所知,dart从SDK 2.8开始支持UDS。我尝试寻找其他函数而不是

ClientChannel
我什至尝试使用
file:///tmp/test.socket
作为输入字符串。

此外,当将 go server 和 flutter client 都更改为使用 TCP 时,它工作正常。

颤振代码:

import 'package:flutter/material.dart';
import 'proto/src/service.pbgrpc.dart';
import 'package:grpc/grpc.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int result = 0;
  Sequence input = Sequence();
  SumServiceClient client = SumServiceClient(ClientChannel(
      'unix:///tmp/test.socket',
      options:
          const ChannelOptions(credentials: ChannelCredentials.insecure())));

  void _callGrpcService() async {
    input.sequence.add(10);
    var response = await client.sumSequence(input);
    setState(() {
      result = response.sum;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Center(
            child: Column(children: <Widget>[
          const Text(
            'gRPC example',
          ),
          Text(
            '$result',
            style: Theme.of(context).textTheme.displayMedium,
          ),
        ])),
        floatingActionButton: FloatingActionButton(
            onPressed: _callGrpcService, child: const Icon(Icons.play_arrow)));
  }
}

去服务器:

package main

import (
    "context"
    "log"
    "net"
    "os"
    "os/signal"
    "syscall"

    pb "rpc/demo/proto"

    "google.golang.org/grpc"
)

type sumServer struct {
    pb.SumServiceServer
}

func (s *sumServer) SumSequence(ctx context.Context, req *pb.Sequence) (*pb.Sum, error) {
    var sum int32
    for _, element := range req.Sequence {
        sum += element
    }

    return &pb.Sum{
        Sum: sum,
    }, nil
}

const port = ":9000"

func main() {
    laddr, err := net.ResolveUnixAddr("unix", "/tmp/test.socket")
    listener, err := net.ListenUnix("unix", laddr)
    // listener, err := net.Listen("tcp", "localhost"+port)
    grpcServer := grpc.NewServer()

    signalChannel := make(chan os.Signal, 1)
    signal.Notify(signalChannel, os.Interrupt, os.Kill, syscall.SIGTERM)

    go func(c chan os.Signal) {
        sig := <-c
        log.Printf("Caught signal %s, shutting down.", sig)
        grpcServer.Stop()
        os.Exit(0)
    }(signalChannel)

    if err != nil {
        log.Fatalf("Failed to start the server %v", err)
    }

    pb.RegisterSumServiceServer(grpcServer, &sumServer{})
    log.Printf("Server started at %v", listener.Addr())
    if err := grpcServer.Serve(listener); err != nil {
        log.Fatalf("Failed to start gRPC server %v", err)
    }
}

原型文件:

syntax = "proto3";

option go_package = "./proto";

package sum_service;

service SumService {
  rpc SumSequence(Sequence) returns (Sum) {}
}

message Sequence {
  repeated int32 sequence = 1;
}

message Sum {
  int32 sum = 1;
}

据我所知,dart 支持使用 unix 套接字。这是Flutter的socket权限的问题吗?有没有

ClientChannel
以外的连接UDS的功能?还是我在 flutter 中缺少 UDS 初始化函数?

flutter dart sockets grpc unix-socket
1个回答
0
投票

正如我所怀疑的。我们需要将 unix 套接字转换为

InternetAddress
。使用

final InternetAddress host = InternetAddress('tmp/test.socket', type:InternetAddressType.unix);

并在没有端口的情况下在

host
内使用
ClientChannel

或者直接插上:

  SumServiceClient client = SumServiceClient(ClientChannel(
      InternetAddress('/tmp/test.socket', type: InternetAddressType.unix),
      options:
          const ChannelOptions(credentials: ChannelCredentials.insecure())));

© www.soinside.com 2019 - 2024. All rights reserved.