Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
grpcui -plaintext 127.0.0.1:50051 



Sample Code

Code Block
languagebash
titleSampleServerClient
collapsetrue
package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"net"
	"os"
	"time"

	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"google.golang.org/grpc/examples/helloworld/helloworld"
	"google.golang.org/grpc/encodingreflection"
)

const (
	defaultAddress = "127.0.0.1:50051"
	serviceName    = "sample.Greeter"
	methodName     = "/sample.Greeter/SayHello"
)

func init() {
	encoding.RegisterCodec(jsonCodec{})
}

type HelloRequestgreeterServer struct {
	Name string `json:"name"`
}

type HelloReply struct {
	Message   string `json:"message"`
	Timestamp string `json:"timestamp"`
}

type jsonCodec struct{}

func (jsonCodec) Marshal(v any) ([]byte, error) {
	return json.Marshal(v)helloworld.UnimplementedGreeterServer
}

func (jsonCodec) Unmarshal(data []byte, v any) error {
	return json.Unmarshal(data, v)
}

func (jsonCodec) Name() string {
	return "json"
}

type greeterService interface {
	SayHello(context.Context, *HelloRequest) (*HelloReply, error)
}

type greeterServer struct{}

func (greeterServer) SayHello(_ context.Context, req *helloworld.HelloRequest) (*helloworld.HelloReply, error) {
	name := req.NameGetName()
	if name == "" {
		name = "friend"
	}

	return &helloworld.HelloReply{
		Message:   fmt.Sprintf("Hello, %s!", name),
		Timestamp: time.Now().Format(time.RFC3339),
	}, nil
}

var greeterServiceDesc = grpc.ServiceDesc{
	ServiceName: serviceName,
	HandlerType: (*greeterService)(nil),
	Methods: []grpc.MethodDesc{
		{
			MethodName: "SayHello",
			Handler:    sayHelloHandler,
		},
	},
	Streams:  []grpc.StreamDesc{},
	Metadata: "sample",
}

func sayHelloHandler(srv any, ctx context.Context, dec func(any) error, interceptor grpc.UnaryServerInterceptor) (any, error) {
	req := new(HelloRequest)
	if err := dec(req); err != nil {
		return nil, err
	}

	baseHandler := func(ctx context.Context, req any) (any, error) {
		return srv.(greeterService).SayHello(ctx, req.(*HelloRequest))
	}

	if interceptor == nil {
		return baseHandler(ctx, req)
	}

	info := &grpc.UnaryServerInfo{
		Server:     srv,
		FullMethod: methodName,
	}
	return interceptor(ctx, req, info, baseHandler)
}

func main() {
	mode := flag.String("mode", "server", "server or client")
	addr := flag.String("addr", defaultAddress, "address to listen on or connect to")
	name := flag.String("name", "gRPC", "name to send in client mode")
	flag.Parse()

	logger := log.New(os.Stderr, "grpc-sample: ", log.LstdFlags)

	switch *mode {
	case "server":
		if err := runServer(*addr, logger); err != nil {
			logger.Fatal(err)
		}
	case "client":
		if err := runClient(*addr, *name, logger); err != nil {
			logger.Fatal(err)
		}
	default:
		logger.Fatalf("unsupported mode %q, use server or client", *mode)
	}
}

func runServer(addr string, logger *log.Logger) error {
	lis, err := net.Listen("tcp", addr)
	if err != nil {
		return fmt.Errorf("listen on %s: %w", addr, err)
	}

	server := grpc.NewServer(grpc.ForceServerCodec(jsonCodec{}))
	serverhelloworld.RegisterServiceRegisterGreeterServer(&greeterServiceDescserver, greeterServer{})
	reflection.Register(server)

	logger.Printf("server listening on %s with reflection enabled", addr)
	return server.Serve(lis)
}

func runClient(addr, name string, logger *log.Logger) error {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	conn, err := grpc.DialContext(
		ctx,
		addr,
		grpc.WithTransportCredentials(insecure.NewCredentials()),
		grpc.WithBlock(),
		grpc.WithDefaultCallOptions(grpc.ForceCodec(jsonCodec{})),
	)
	if err != nil {
		return fmt.Errorf("connect to %s: %w", addr, err)
	}
	defer conn.Close()

	reqclient := &HelloRequest{Name: name}
	resp := new(HelloReplyhelloworld.NewGreeterClient(conn)
	ifresp, err := connclient.InvokeSayHello(ctx, methodName, req, resp);&helloworld.HelloRequest{Name: name})
	if err != nil {
		return fmt.Errorf("invoke %sSayHello: %w", methodName, err)
	}

	logger.Printf("response: %s (%s)", resp.Message, resp.TimestampGetMessage())
	return nil
}


References

...