LoginSignup
7
3

More than 3 years have passed since last update.

GoとSwiftでWebSocketとProtobufを使ったデータ通信

Last updated at Posted at 2019-08-09

概要

業務でGoとSwift間でwebsocketでProtobufのデータをやりとりするという案件があったので色々と調査してSampleを作ってみた。

Githubレポジトリ

ライブラリ選定理由

クライアント側のライブラリはStarscream

  • objective-cで作成されていてあまりメンテナンスされていないSocketRocketは除外
  • socket.ioはサーバ側の言語がGolang非対応なのでsocket.io-client-swiftもなし(今回はサーバ側がGoだったため)
  • StarscreamとSwiftWebsocketはあまり変わらないが、人気度と知見の量的にStarscream(参考:https://ios.libhunt.com/compare-starscream-vs-swiftwebsocket?rel=cmp-cmp)

サーバ側はgorilla/websocket

This package currently lacks some features found in an alternative and more actively maintained WebSocket package:
https://godoc.org/github.com/gorilla/websocket

下記を見ればわかるように標準の方が機能が多く不足しているため

github.com/gorilla golang.org/x/net
RFC 6455 Features
Passes Autobahn Test Suite Yes No
Receive fragmented message Yes No, see note 1
Send close message Yes No
Send pings and receive pongs Yes No
Get the type of a received data message Yes Yes, see note 2
Other Features
Compression Extensions Experimental No
Read message using io.Reader Yes No, see note 3
Write message using io.WriteCloser Yes No, see note 3

WebSocket Client ライブラリ比較

Starscream

レポジトリ情報

メリット

  • サーバ側が通常のwebsocketが使える
  • 軽量

デメリット

  • websocketが繋がらない場合にpollingなどをする場合自前で書かなければならない

Socket.io-client-swift

レポジトリ情報

仕様

  • Clientでこれを使う場合、Serverもsocket.ioは必須っぽい(内部的にsocketURLなどに/socket.io/のpathなどが付与されている)

メリット

  • socket.ioが使える
    • WebSocketが繋がらなかった時に代替手段としてLong Pollingpollingを行ってくれる
  • objective-cでも使える

デメリット

  • サーバ側もsocket.ioを使わなければならない
    • socket.ioはもともとnode.js用サーバー側ライブラリとブラウザ用JavaScriptライブラリのセットなのでgolangでのsupportがない。一応go-socket.ioというライブラリがあるが、現状でsocket.ioのversion1.4までしかsupportしていない

SwiftWebSocket

レポジトリ情報

メリット

  • Starscream同様
  • Objective-cでも使える

デメリット

  • 知見が少ない

SocketRocket

レポジトリ情報

メリット

  • 知見が多い

デメリット

  • コードがほぼobjective-cであるため内部実装が読みにくい

ProtocolBufferについて

概要

こちらを読んでもらえば大体こんな感じかっていうのは理解できる。
要約すると下記のような感じで書いている

Protocolbufferはスキーマ言語でGoogleが内部で利用しているシリアライゼーション形式である。
スキーマ言語が今人気になった理由は、単一のDBなどにデータを保存していたような昔と違い、
データはあちこちのいろんなストレージ技術で保存されたり、バックエンドも単一サービスではなくて分割されていたりする。
また、クライアントもweb版, iOS版, Android版それぞれ別の言語で実装されていたりするからだ。
JSON schemeは可読性に難がある。
Protobufがいい理由は簡素で可読で、割と何にでも使えて、しかしすべてをカバーしようとして膨れあがっておらず、ツールを拡張可能。
とりわけ何かがすごく良いという訳でもないけれども、すこし使い込めばこの素朴さが手に馴染みやすい。

導入にあたって

メリット

  • サーバ側クライアント側で余計なすり合わせが発生しにくい
  • バイナリデータでやりとりするので軽量

デメリット

  • デバッグは少しやりにくい
  • 導入が少し手間がかかる

定義

message [モデル名] {
    TYPE NAME = UNIQUE NUMBER
}

といった書き方をする。
下記のように定義する。

syntax = "proto3";

message User {
    int32 id = 1;
    string name = 2;
}

導入手順

共通

protocolbufferをinstallする

$ brew install protobuf

client側(swift)

1: swift-protobufをinstall

$ brew install swift-protobuf

2: ファイルの書き出し

$ protoc --swift_out={outputのpath} exsample.proto

3: 書き出したファイルをxcode.projectに追加
4: swift-protobufをpod install

pod 'SwiftProtobuf', '~> 1.0'
  1. structとして使える
guard let user = try? User(serializedData: data) else { return }

server側(golang)

1: protoc-gen-goをinstall

$ go get -u github.com/golang/protobuf/{proto,protoc-gen-go}

2: ファイルの書き出し

$ protoc --go_out={outputのpath} exsample.proto

3: goファイルが書き出されるのでgo側からimportすれば、定義モデルが使える

参考

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3