概要
業務で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
- 標準パッケージである https://godoc.org/golang.org/x/net/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
レポジトリ情報
- https://github.com/daltoniam/Starscream
- ★5,106
- 最終更新日: 3ヶ月前
- Swift
- Objective-CはJetfire
- framework size: 942KB
- first commit: Commits on Jul 17, 2014
メリット
- サーバ側が通常のwebsocketが使える
- 軽量
デメリット
- websocketが繋がらない場合にpollingなどをする場合自前で書かなければならない
Socket.io-client-swift
レポジトリ情報
- https://github.com/socketio/socket.io-client-swift
- ★3,797
- 最終更新日: 2ヶ月前
- Swift
- Objective-cからでも使える
- framework size: 1.4MB
- 内部的にStarscreamを使っている。
- websocketのライブラリではなくsocket.ioのライブラリ(https://github.com/socketio/socket.io-client--swift/blob/6cfea5aca32bd1ebafccc4c4f1fb7f71e1b2e9ce/Usage%20Docs/FAQ.md)
仕様
- Clientでこれを使う場合、Serverもsocket.ioは必須っぽい(内部的にsocketURLなどに/socket.io/のpathなどが付与されている)
メリット
- socket.ioが使える
-
WebSocket
が繋がらなかった時に代替手段としてLong Polling
やpolling
を行ってくれる
-
- objective-cでも使える
デメリット
- サーバ側もsocket.ioを使わなければならない
- socket.ioはもともと
node.js用サーバー側ライブラリとブラウザ用JavaScriptライブラリのセット
なのでgolangでのsupportがない。一応go-socket.ioというライブラリがあるが、現状でsocket.ioのversion1.4までしかsupportしていない
- socket.ioはもともと
SwiftWebSocket
レポジトリ情報
- https://github.com/tidwall/SwiftWebSocket
- ★1,262
- 最終更新日: 3ヶ月前
- Swift
- Objective-cでも使える
- first commit: May 27, 2015
メリット
- Starscream同様
- Objective-cでも使える
デメリット
- 知見が少ない
SocketRocket
レポジトリ情報
- https://github.com/facebook/SocketRocket
- ★8,660
- 最終更新日: 1年前
- Objective-C
メリット
- 知見が多い
デメリット
- コードがほぼ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'
- 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すれば、定義モデルが使える