FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

Pokemon Goを支える技術: Protocol Bufferとは何なのか

f:id:msyksphinz:20160723175322p:plain

Pokemon Goが日本上陸となり、猫も杓子もポケモンゲットとなっているが、私はポケモン世代にも関わらず、モンスターや生き物に全く興味を抱かなかった少年時代であったため、知っているポケモンピカチュウくらいしかいない。

そんな中、Pokemon Go上陸したんだなーとTwitterを見ていると、通信の部分にはGoogleのProtoBufが利用されているという話を聞いて、面白そうなのでどのような技術なのか調査してみることにした。

Pokemon Go decoded GAME_MASTER protobuf file v0.1 · GitHub

GitHub - Mila432/Pokemon_Go_API: Pokémon GO API in Python

プロトコルバッファとは何なのか

そもそもProtocol Bufferとは何なのか、その知識さえ欠けていたので調査してみたところ、以下のページがヒットした。2008年の記事でずいぶんと古いが、内容は分かり易く、とっつきやすい。

news.mynavi.jp

プログラム中のデータ構造など、そのままの構造で送受信してしまうとパケットサイズが大きくなってしまい、通信量に問題が発生する。 これを解決するために、プログラミング言語で共通のプロトコルバッファの構造に一度変換し、より効率的なサイズに変更してからデータを送受信することでデータ通信量を抑える、というのが発想のようだ。 このような機構のことを一般的にデータシリアライザと呼ぶ。

Developer Guide  |  Protocol Buffers  |  Google Developers

Protocol buffers are a flexible, efficient, automated mechanism for serializing structured data – think XML, but smaller, faster, and simpler.

では、既存の技術との違いは何なのか。既存の技術としてはXML, JSONなどがあるらしいが、正直こちらの技術もあまり明るくない。ただ解説サイトなどを読み進める限り、バイナリフォーマットを採用することでデータ量を圧縮し、より多くのプログラミング言語に対応していることが利点と言えよう。

プロトコルバッファを試してみる

今回はとりあえず Protocol Bufferの導入部分のみを試してみよう。UbuntuにProtocl Bufferをインストールし、メッセージ形式を定義する所まで進んでみる。

参考にするのは Google の Protocol Bufferの解説サイトで、インストールの部分をそのまま読み進めていく。

github.com

ちなみにインストールには4GB程度のメモリが必要のようだ。でないとmake checkで失敗する。

git clone https://github.com/google/protobuf.git --recurse-submodules
sudo apt-get install autoconf automake libtool curl make g++ unzip
./autogen.sh
./configure
make
make check
sudo make install
sudo ldconfig # refresh shared library cache.

インストールに必要なのは15分程度だった。これでインストール完了だ。

$ protoc --version
libprotoc 3.0.0

プロトコルバッファのメッセージ形式を定義する

まずは、メッセージ形式を定義して、通信フォーマットを定義してみよう。

news.mynavi.jp

ちなみに上記のサイトでは情報が若干古く、最初にどのバージョンのprotocol bufferの文法を利用するのか指定する必要がある。

syntax = "proto3";

message Person {
  string name = 1;
  int32 age = 2;
}

上記ではmessage形式Personを定義しており、 nameタグ(タグID=1)、ageタグ(タグID=2)を定義している。Proto2で必要だったrequired, optionalなどの識別子はProto3では不要なようだ。

コンパイルしてメッセージ形式を作成する

以下のようにすると、C++ソースコードとヘッダファイルが作成され、プロトコルバッファを用いたメッセージ通信のためのテンプレートが作成される。

$ protoc --cpp_out ./ Person.proto
$ ls
Person.pb.cc  Person.pb.h  Person.proto

ここで定義されたライブラリを使えば、プロトコルバッファを使った通信が出来るようになるという訳だ。