본문 바로가기
gRPC

gRPC on Unity 3D (C# proto, server, client Example)

by GiantKing 2021. 6. 15.

gRPC 서비스는 다양한 형식의 메서드가 있다 

  • 단방향
  • 서버 스트리밍
  • 클라이언트 스트리밍
  • 양방향 스트리밍

 

다양한 형식별 proto파일 rpc 작성법 

syntax = "proto3";

service ExampleService {

// Unary

rpc UnaryCall (ExampleRequest) returns (ExampleResponse);

 

// Server streaming

rpc StreamingFromServer (ExampleRequest) returns (stream ExampleResponse);

 

// Client streaming

rpc StreamingFromClient (stream ExampleRequest) returns (ExampleResponse);

 

// Bi-directional streaming

rpc StreamingBothWays (stream ExampleRequest) returns (stream ExampleResponse); }

 

gRPC 서비스 만들기 참고

 

 

단방향 테스트를 해보자

아래 프로토콜 형식으로 메세지를 보낸다고 가정해보자

 

학교

학교 이름

학교 타입

학생들 [{학생 이름, 학생번호}...{}]

 

프로토콜 Json 정의

// Json Example
{ "name": "", "Type": "", "students": [ { "name": "" ,"number"}, { "name": "", "number":  ""}] }

 

프로토콜 형식에 맞춘 Class 정의

// C# Class Example

public class School
{
     public string name;
     public int Type;
     public List<Student> students;
     public class Student
     {
          public string name;
          public int number;
     }
}

 

프로토콜 형식에 맞춘 proto 정의

//proto Example

syntax = "proto3"; 

package MyProject.Test; 

service EchoTest { rpc Ping (PingRequest) returns (PongResponse) {} } //인터페이스 테스트를 위한 Echo 서비스

service SchoolInfo {
     rpc SchoolData (SchoolDataRequest) returns (SchoolDataResponse) {} //학교 1개의 데이터
     rpc SchoolsData (SchoolsDataRequest) returns (SchoolsDataResponse) {} //여러개의 학교 데이터   
}

message PingRequest { string message = 1; }  

message PongResponse { string message = 1; } 

message SchoolDataRequest{
     string name = 1;
}

//학교 구조 정의
message SchoolDataResponse{
     string name = 1;
     int32 Type = 2;
     repeated Student students = 3;
}

//학생 구조 정의
message Student{
     string name = 1;
     int32 number = 2;
}

message SchoolsDataRequest{
     bool dataRequest = 1;
}

message SchoolsDataResponse{
     repeated SchoolDataResponse SchoolsData = 1;
}

 

서버 스크립트

서버 생성 및 Response

// C# Server Example

using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using Grpc.Core;
using MyProject.Test;

public class GrpcServerTest : MonoBehaviour
{
    Server server;
    const string IP = "localhost";
    const int Port = 88888;
    // Start is called before the first frame update
    void Start()
    {
        server = new Server
        {
            Services = { EchoTest.BindService(new EchoTestPingGRPC()),
                 SchoolInfo.BindService(new SchoolDataGRPC())
            },
            Ports = { new ServerPort(IP, Port, ServerCredentials.Insecure) }
        };
        server.Start();
    }
}
public class EchoTestPingGRPC : EchoTest.EchoTestBase
{
    public override Task<PongResponse> Ping(PingRequest request, ServerCallContext context)
    {
        Debug.Log(request.Message);
        return Task.FromResult(new PongResponse { Message = "Echo: " + request.Message });
    }
}

public class SchoolDataGRPC : SchoolInfo.SchoolInfoBase
{
    public override Task<SchoolDataResponse> SchoolData(SchoolDataRequest request, ServerCallContext context)
    {

        School school = new School();

        List<Student> students = new List<Student>();
        
        foreach(var child in school.students)
        {
            Student studentTemp = new Student();
            studentTemp.Name = child.name;
            studentTemp.Number = child.number;
            students.Add(studentTemp);
        }

        return Task.FromResult(new SchoolDataResponse {
            Name = school.name,
            Type = school.Type,
            Students = {students}
        });
    }

    public override Task<SchoolsDataResponse> SchoolsData(SchoolsDataRequest request, ServerCallContext context)
    {
        List<School> schools = new List<School>();

        for(int i = 0; i<10; i++)
            schools.Add(new School());

        List<SchoolDataResponse> schoolDataList = new List<SchoolDataResponse>();

        foreach (var school in schools)
        {
            SchoolDataResponse schoolData = new SchoolDataResponse();
 
            List<Student> students = new List<Student>();

            foreach (var child in school.students)
            {
                Student studentTemp = new Student();
                studentTemp.Name = child.name;
                studentTemp.Number = child.number;
                students.Add(studentTemp);
            }

            var schoolDataTemp = new SchoolDataResponse
            {
                Name = school.name,
                Type = school.Type,
                Students = { students }
            };
            schoolDataList.Add(schoolDataTemp );
        }

        return Task.FromResult(new SchoolsDataResponse
        {
            SchoolsData = {schoolDataList}
        });
    }
}

 

서버 데이터 생성

클래스 객체 생성시 데이터가 만들어진다

public class School
{
    public string name;
    public int Type;
    public List<Student> students;

    public School()
    {
        name = "testSchool";
        Type = 1;
        students = new List<Student>();

        for(int i = 0; i < 10; i++)
            students.Add(new Student(i));
    }
    public class Student
    {
        public string name;
        public int number;
        public Student(int i)
        {
            name = "test = " + i;
            number = i;
        }
    }
}

 

 

클라이언트 생성 및 Request

// C# Client Example

using UnityEngine;
using Grpc.Core;
using MyProject.Test;

public class GrpcClientTest : MonoBehaviour
{
    const string IP = "localhost:";
    const int Port = 88888;

    string mes = "Hi!! Test Echo";
    Channel channel;

    void Start()
    {
        channel = new Channel(IP + Port, ChannelCredentials.Insecure);
        var repley1 = client.SchoolData(new SchoolDataRequest { Name = "testSchool" });
        var repley2 = client.SchoolsData(new SchoolsDataRequest { DataRequest = true });                           

        Debug.Log(repley1.ToString());
        Debug.Log(repley2.ToString());
    }
}

 

학교 하나의 데이터 호출

 

여러개의 학교 데이터 호출

'gRPC' 카테고리의 다른 글

gRPC란 ?  (0) 2021.06.17
gRPC on Unity 3D (Test Example)  (0) 2021.06.14