> ## Documentation Index
> Fetch the complete documentation index at: https://frpc.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Quick Start

In this section we'll be going over how you can quickly get started with <Tooltip tip="Frisbee RPC">fRPC</Tooltip>,
from defining your message types in a <Tooltip tip="Syntax used to describe protocol buffers">proto3</Tooltip> file, to writing your first server and client.

We'll be building a simple echo service that will echo back the message it receives, and later on we'll also show how
you can use the Frisbee framework itself to build a more complex <Tooltip tip="Publish and Subscribe">PUB/SUB</Tooltip> service.

# Installation

To get started with <Tooltip tip="Frisbee RPC">fRPC</Tooltip>, you'll need to make sure you have `Go`
and the `protoc` compiler installed. Then, you'll need to install
the `protoc-gen-go-frpc` <Tooltip tip="Plugins hook into the protoc compiler and allow for custom code generation">protoc plugin</Tooltip>
which we will use to generate the server and client code.

## Prerequisites

* [Go](https://golang.org) - fRPC works with `Go` version 1.18 or later. For installation instructions see [Go's Getting Started Guide](https://golang.org/doc/install).
* [Protocol Buffer Compiler (protoc)](https://developers.google.com/protocol-buffers) - fRPC works with `protoc` version 3. For installation instructions see the [Protoc Getting Started Guide](https://developers.google.com/protoc/docs/getting_started).

If you're using MacOS and have [Brew](https://brew.sh/) installed, you can use `brew install go`
to install Golang, and `brew install protoc` to install the protoc compiler.

## Install the fRPC Plugin

To install the `protoc-gen-go-frpc` plugin, you'll first need to make sure that your `$GOBIN` environment variable is set and available in
your system path. See the [Go Environment Variables](https://golang.org/doc/code.html#GOPATH) page
for more information, but in general, you can do this by adding the following to
your `~/.bashrc` file:

```sh .bashrc
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOBIN
```

To install the `protoc-gen-go-frpc` plugin itself, you'll need to run the following command:

```bash
$ go install github.com/loopholelabs/frpc-go/protoc-gen-go-frpc@latest
```

This will install the `protoc-gen-go-frpc` plugin into your `$GOBIN` directory
where it will be available for use by the `protoc` compiler.

You can check that the plugin is installed and available by running the following command:

```bash
$ which protoc-gen-go-frpc
/Users/<username>/go/bin/protoc-gen-go-frpc # or $GOPATH/bin/protoc-gen-go-frpc
```

# Create a Proto3 File

Now that we have the prerequisites and the `protoc-gen-go-frpc` plugin installed,
we can start writing our echo service. Let's start by creating a directory to house our project:

```bash
$ mkdir -p ~/frpc
$ cd ~/frpc
```

Now we'll create an `echo.proto` file and define our message types:

```protobuf echo.proto
option go_package = "/echo";

message Request {
  string Message = 1;
}

message Response{
  string Message = 1;
}
```

You can see that we've defined two message types, one for the `Request` and one for the `Response`.

Next, we will define a new `EchoService` in our `proto3` file. This tells the compiler that we want to generate a server and client for this service.

```protobuf echo.proto
option go_package = "/echo";

service EchoService {
  rpc Echo(Request) returns (Response);
}

message Request {
  string Message = 1;
}

message Response{
  string Message = 1;
}
```

And with that you should be ready. Next we'll start the `protoc` compiler to generate
our fRPC server and client.

# Generate the Server and Client

Let's run the following command to generate the server and client code:

```bash
$ protoc --go-frpc_out=. echo.proto
```

This command tells the `protoc` compiler to generate the server and client code for us and
by specifying the `--go-frpc_out` flag, we're implicitly specifying that we want to use the `protoc-gen-go-frpc` plugin.

If we wanted to be more explicit, we could have run the following command:

```bash
$ protoc --plugin=protoc-gen-go-frpc=$GOBIN/protoc-gen-go-frpc --go-frpc_out=. echo.proto
```

These commands should have generated a new folder at `~/frpc/echo`, which
contains an `echo.frpc.go` file containing the server and client code. Within
that file, you'll find the following interface:

```go echo.frpc.go
...

type EchoService interface {
	Echo(context.Context, *Request) (*Response, error)
}

...
```

All we have left to do is implement the `EchoService` interface with our server-side logic,
and pass that into the server. The generated library will then be able to handle everything else for us.

# Setting up the Server

To set up our server, we simply need to implement the `EchoService` interface and then start
the server. We'll start by creating a new `server/main.go` file in our `~/frpc` directory:

```go server/main.go
package main

import (
	"context"
    "frpc/echo"
)

type svc struct{}

func (s *svc) Echo(_ context.Context, req *echo.Request) (*echo.Response, error) {
	res := new(echo.Response)
	res.Message = req.Message
	return res, nil
}
```

As you can see we've created a new struct called `svc` and implemented the `EchoService` interface by
creating a new function called `Echo` which takes a `context.Context` and an `*echo.Request` object.
We aren't really using the context in this example so we just ignore that and instead return an `*echo.Response` object with the
same message as the request.

Now we can implement the server itself:

```go server/server.go
package main

import (
	"context"
	"github.com/rs/zerolog"
    "frpc/echo"
	"log"
	"os"
	"runtime"
	"time"
)

type svc struct{}

func (s *svc) Echo(_ context.Context, req *echo.Request) (*echo.Response, error) {
	res := new(echo.Response)
	res.Message = req.Message
	return res, nil
}

func main() {
	frpcServer, err := echo.NewServer(new(svc), nil, nil)
	if err != nil {
		panic(err)
	}

	err = frpcServer.Start(":8080")
    if err != nil {
        panic(err)
    }
}
```

This additional `main` function runs when the server starts up, and passes in our `svc` struct to the
generated `echo.NewServer()` function. It then binds the server to port `:8080` and starts listening for connections.

We're passing in `nil` for both the `*tls.Config` and `logging` parameters in the generated `echo.NewServer()` function because
we don't want to use TLS or logging in this example.

# Setting up the Client

To set up our client, we don't need to implement any additional logic, but we do need to create a new `client/main.go` file
in our `~/frpc` directory:

```go client/main.go
package main

import (
	"context"
	"fmt"
	"frpc/echo"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	c, err := echo.NewClient(nil, nil)
	if err != nil {
		panic(err)
	}

	err = c.Connect("127.0.0.1:8080")
	if err != nil {
		panic(err)
	}
}
```

Here, we're creating a new echo client using our generated `echo.NewClient()` function.
Then, we're passing in the address of the server we want to connect to. But we're not actually sending any
requests to the server yet.

To do that, we can write a simple look to send a request to the server every second and then print out the response:

```go echo/client/client.go
package main

import (
	"context"
	"fmt"
	"frpc/echo"
	"log"
	"os"
	"os/signal"
	"syscall"
	"time"
)

func main() {
	c, err := echo.NewClient(nil, nil)
	if err != nil {
		panic(err)
	}

	err = c.Connect("127.0.0.1:8080")
	if err != nil {
		panic(err)
	}

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

	req := echo.NewRequest()
	i := 0
	for {
		select {
		case <-stop:
			err = c.Close()
			if err != nil {
				panic(err)
			}
			return
		default:
			req.Message = fmt.Sprintf("#%d", i)
			log.Printf("Sending Request %s\n", req.Message)
			res, err := c.EchoService.Echo(context.Background(), req)
			if err != nil {
				panic(err)
			}
			log.Printf("Received Response %s\n", res.Message)
			time.Sleep(time.Second)
			i++
		}
	}
}
```

The above loop registers a `stop` channel to receive a signal when the user hits `Ctrl+C`,
and then starts sending a request to the server every second.

And that's it! We've now set up a simple echo client that can send requests to our server and print out the response.

We were able to use a simple `proto3` file to define our request and response objects, and all we had to do was
implement the `EchoService` interface. Everything else was handled for us by **fRPC**.

The complete code for this example is available in the [frpc-echo-example](https://github.com/loopholelabs/frpc-echo-example)
repository on [Github](https://github.com/loopholelabs).

# Next Steps

Now that we've seen how easy it is to use **fRPC**, we recommend you check out our [benchmarks](/performance/grpc-benchmarks) pages
to learn more about how **fRPC** fares against other RPC frameworks.

If you want to learn more about how **fRPC** works under the hood, you can check out our [fRPC Concepts](/getting-started/concepts) page, or our [technical reference](/reference/overview).

Finally, if you'd like to learn how to use [Frisbee](https://github.com/loopholelabs/frisbee-go) (the underlying transport mechanism for fRPC)
to implement your **own messaging protocol** that's fast and performant, you can check out the [frisbee-go Github repository](https://github.com/loopholelabs/frisbee-go).

If you need any help or have any feedback about Frisbee or fRPC, please to check out our [Discord Community](https://loopholelabs.io/discord)!
Our team would love to hear your thoughts and understand how you're planning on using fRPC, and we're always happy to help!
