-1

I am relatively new in GRPC and unable to solve this issue. Could anyone please suggest what is the problem in the client side function due to which it has been showing undefined after running go run main.go for the client side file

greet.proto file

syntax = "proto3";

option go_package = "./proto";

package greet_service;

// Define a service for saying hello
service GreetService {
  rpc SayHello(NoParam) returns (HelloResponse);
  
  rpc SayHelloServerStreaming(NamesList) returns (stream HelloResponse);
  
  rpc SayHelloClientStreaming(stream HelloRequest) returns (MessagesList);
  
  rpc SayHelloBidirectionalStreaming(stream HelloRequest) returns (stream HelloResponse);
}

// Define messages that the service uses
message NoParam {}

message HelloRequest {
  string name = 1;
}

message HelloResponse {
  string message = 1;
}

message NamesList {
  repeated string names = 1;
}

message MessagesList {
  repeated string messages = 1;
}

This code defines a gRPC service called GreetService that has four methods: SayHello, SayHelloServerStreaming, SayHelloClientStreaming, and SayHelloBidirectionalStreaming. The service communicates using messages defined by the NoParam, HelloRequest, HelloResponse, NamesList, and MessagesList message types.

server/main.go

package main

import (
    pb "GRPC_DEMO/proto"
    "google.golang.org/grpc"
    "log"
    "net"
)

const (
    port = ":8080"
)

type helloServer struct {
    pb.GreetServiceServer
}

func main() {
    lis, err := net.Listen("tcp", port)
    if err != nil {
        log.Fatalf("failed to connect to server: %v", err)
    }

    grpcServer := grpc.NewServer()

    pb.RegisterGreetServiceServer(grpcServer, &helloServer{})
    log.Println("Server is running on port:", lis.Addr())

    if err := grpcServer.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

server/server_stream.go

package main

import (
    pb "GRPC_DEMO/proto"
    "log"
    "time"
)

func (s *helloServer) SayHelloServerStreaming(req *pb.NamesList,
    stream pb.GreetService_SayHelloServerStreamingServer) error {

    log.Printf("Received names: %v", req.Names)

    for _, name := range req.Names {
        res := &pb.HelloResponse{
            Message: "Hello" + name + ", how are you?",
        }

        if err := stream.Send(res); err != nil {
            log.Fatalf("failed to send response: %v", err)
        }
        time.Sleep(2 * time.Second)
    }

    return nil
}

client/main.go

package main

import (
    pb "GRPC_DEMO/proto"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    "log"
)

const (
    port = ":8080"
)

func main() {

    conn, err := grpc.Dial("localhost"+port, grpc.WithTransportCredentials(insecure.NewCredentials()))
    if err != nil {
        log.Fatalf("failed to connect to server: %v", err)
    }

    defer conn.Close()

    client := pb.NewGreetServiceClient(conn)

    names := &pb.NamesList{
        Names: []string{"John", "Sunny"},
    }

    // UNARY RPC
    //callSayHello(client)

    // SERVER STREAMING RPC
    callSayHelloServerStream(client, names)
}

client/server_stream.go

package main

import (
    pb "GRPC_DEMO/proto"
    "context"
    "io"
    "log"
)

func callSayHelloServerStream(client pb.GreetServiceClient, names *pb.NamesList) {

    log.Printf("Calling SayHelloServerStreaming RPC...")

    stream, err := client.SayHelloServerStreaming(context.Background(), names)
    if err != nil {
        log.Fatalf("failed to call SayHelloServerStreaming: %v", err)
    }

    for {
        message, err := stream.Recv()
        if err == io.EOF {
            log.Printf("No more response from server...")
            break
        }
        if err != nil {
            log.Fatalf("failed to receive response: %v", err)
        }

        log.Printf("Response from server: %v", message.Message)
    }
    log.Printf("Finished SayHelloServerStreaming RPC...")

}

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • 1
    Do not use filename arguments to go run. – Volker Jun 16 '23 at 18:12
  • 1
    Nit: you define 'port' in client|server as `:8080`. The string `:8080` represents an address (not a port). The port is `8080`, prefixing it with `:` is usually equivalent to meaning the IP address (`0` more commonly `0.0.0.0`) and so `:8080` == `0:8080` == `0.0.0.0:8080`. – DazWilkin Jun 16 '23 at 18:51

1 Answers1

0

as suggested by @Volker the issue is due to how you execute the programs. If you try to run the server with the command go run main.go and then the client with go run main.go, you'll get back the undefined xxx error. If you specify the filename you're not building the whole main package (I'd say that you're executing only the specified file).
Here is the solution.
I repro on my local machine your code and overall is fine (for sure something to improve but maybe you simplified it for the sake of the demo).
Then, you've two options to execute:

  1. Open two shells in the terminal. In the first one, execute go run .. You must be located within the server folder. In the second one, execute the same command (go run .) but located within the client folder.
  2. Alternatively, you can execute the command go build in both folders and you'll have two executables files (server and client). Then, you can run them with the commands ./server and ./client.

Please note that, if you don't like these names, you'll always have the option to use the argument -o to give a different name (e.g. go run -o test_client).

Let me know if this clarifies your issue, thanks!

ossan
  • 1,665
  • 4
  • 10