프로그래밍/의문

유니티 클라이언트와 c++ 서버 플랫 버퍼로 통신하기 성공~

제페 2017. 12. 4. 22:10
반응형

c++ 서버는 boost/asio 기반으로 만들었다.


#include <iostream>
#include <iterator>
#include <nta/tcp.hpp>
#include "packets.h"

class flatbuffers_filter : public nta::receive_filter // 아직 작성되지 않음
{
public:
virtual result feed(const std::byte* data, std::size_t size) {
return drain(size);
}
};

class session : public nta::tcp::session
{
public:

session(nta::tcp::session_params params) :
nta::tcp::session(std::move(params))
{
}

virtual void on_opened() override
{
std::cout << "opened" << std::endl;
flatbuffers::FlatBufferBuilder builder;
builder.Finish(MyGames::packet::CreateVector2(builder, 10.0f, 10.0f));
auto data = builder.GetBufferPointer();
auto size = builder.GetSize();
std::vector<char> buffer(sizeof(packet::header) + size);
packet::header header{ 0, size };
std::memcpy(buffer.data(), &header, sizeof(header));
this->send(buffer.data(), buffer.size());
}

virtual void on_closed() override
{
}

virtual void on_received(const std::error_code& err, const nta::packet& packet) override
{
if (err)
this->close();
}

virtual void on_sent(const std::error_code &) override
{
}

};

int main(){
nta::tcp::server_builder builder;
builder
.endpoint("localhost:16333")
.max_sessions(1)
.session <session>();
std::shared_ptr<nta::tcp::server> server = builder.build();
server->run();
return 0;
}


유니티 클라이언트는 c#을 이용해서 만들었다.


플랫 버퍼의 총 크기는 알 수 없으므로 패킷 헤더에 타입과 사이즈를 넣었다. 헤더의 사이즈엔 플랫버퍼의 크기가 기록된다.


받은 데이터가 헤더를 제외하고 헤더에 명시된 플랫버퍼 크기 이상을 받았다면 그만큼 잘라서 쓰면 된다.

type은 플랫버퍼를 바이너리를 역직렬화 할 때 어떤 변환을 거칠 것인지 판단을 할 기준이 있어야 하기 때문에 반드시 필요하다.

using System.Collections.Generic;
using UnityEngine;
using Assets;
using System.Net;
using FlatBuffers;

public class GameController : MonoBehaviour {

  RemoteServer server;
  HashSet<GameObject> objects = new HashSet<GameObject>();

  // Use this for initialization
  void Start ()
{
    server = new RemoteServer(new IPEndPoint(IPAddress.Loopback, 16333), (int type, byte[] body)=>
    {
      switch(type)
      {
        case 0:
          {// 타입 0이면 Vector2로 변환하는 처리!
            var vec2 = MyGames.packet.Vector2.GetRootAsVector2(new ByteBuffer(body));
            Debug.Log(string.Format("{0} {1}", vec2.X, vec2.Y));
          }
          break;
      }
      
    });
    server.Start();
  }

  void Update ()
{
    server.Update();
  }
}


접속하면 c++ 서버에서 10, 10을 보내고 유니티 클라이언트에서 10, 10을 받았다. 많이 다듬어야겠지만 물꼬는 틀었다 ~_~ 


반응형