C#でエンディアン指定して符号なし変数に変換する。
Webの通信なのでBinaryデータを扱って、通信先でデコードする場合エンディアンを指定する必要があります。 Webでは基本的にBigEndian形式で変換されたデータを使用して、通信が行われます。一方PC上の内部構造はLittleEndianが使用されています。 C#でリトルエンディアンをビッグエンディアンに変換する - PG日誌
下記でPC上でどちらが使用されているかを確認することが可能です。
Console.WriteLine(BitConverter.IsLittleEndian);
ネットワークの場合、符号付き整数を扱う場合のみ、 IPAddress.NetworkToHostOrder
を使用すればBigEndian方式に変換することが可能です。IPAddress.NetworkToHostOrder メソッド (System.Net) | Microsoft Docs
しかし、符号なし整数の場合は、Network関係のメソッドにはメソッドが用意されていないので、別のメソッドを使用する必要がある。
そこで発見したのがBinaryPrimitives.ReadInt16LittleEndian(ReadOnlySpan<Byte>) メソッド (System.Buffers.Binary) | Microsoft Docs
using System.Buffers.Binary; var value = 16UL; // BitConverterはLittleEndianでエンドードさていている。 var intValue = BitConverter.GetBytes(value); Console.WriteLine(BinaryPrimitives.ReadUInt64LittleEndian(new ReadOnlySpan<byte>(intValue))); var bytes = new byte[8]; // BigEndianでエンコード、デコードする。 BinaryPrimitives.WriteUInt64BigEndian(bytes, value); Console.WriteLine(BinaryPrimitives.ReadInt64BigEndian(new ReadOnlySpan<byte>(bytes)));
参考
golang のtoolの管理に関して
開発をしているとソース内では使用しないが、便利なtoolをgo get
しバージョンの管理をしておきたいことがある。
例えば、golang.org/x/tools/cmd/stringer
など。
しかし、go module
で依存関係を管理している場合、ソースないで使用されていないライブラリは管理できないという制約がある。これをtools.go
を作成する方法で回避できるのでメモしておく。
// +build tools package tools import _ "golang.org/x/tools/cmd/stringer"
build時に今回作成したtoolsファイルが除外される様にbuild constraintsを使用している。
これを使用することで、build -tags=hoge
で切り替えを行うことが可能であるが、これを指定しないので、binaryにはtoolsのファイルは含まれない事になる。
for { select {....} }はbreakではfor文を抜けられ無い
golangでtimeoutなどの処理を書く場合に、下記の様にfor文内にselectを記述することがある。 (この時Timeout時にはfor文を抜けたいとす。)
for { select { case someChannel: // timeout以外の処理 case time.After(1 * time.Secound): // timeout時の処理 break } }
しかし、単純にbreakを記述しても、for文を抜けることは出来ない。 for文を抜けるには、Labelを用いてbreakをする必要がある。
Loop: for { select { case someChannel: // timeout以外の処理 case time.After(1 * time.Secound): // timeout時の処理 break Loop } }
また、break
ではなく、return
を使って関数から抜けることを行えば、labelを使用する必要はなくなる。
ioパッケージでのファイル書き込み
goのioパッケージにはOpenFile
という関数がある。これは、ファイル名、ファイルに対する操作、ファイルのPermissionを設定して、File構造体を作成する関数であうる。
io.OpenFile(filename string, flag int, permission int)
ファイルに対する操作
ファイルの操作には下記の通りである。
const ( // Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified. O_RDONLY int = syscall.O_RDONLY // open the file read-only. O_WRONLY int = syscall.O_WRONLY // open the file write-only. O_RDWR int = syscall.O_RDWR // open the file read-write. // The remaining values may be or'ed in to control behavior. O_APPEND int = syscall.O_APPEND // append data to the file when writing. O_CREATE int = syscall.O_CREAT // create a new file if none exists. O_EXCL int = syscall.O_EXCL // used with O_CREATE, file must not exist. O_SYNC int = syscall.O_SYNC // open for synchronous I/O. O_TRUNC int = syscall.O_TRUNC // truncate regular writable file when opened. )
ここで、注目いたいのはO_RDONLY
、O_WRONRY
、O_RDWR
は必ず一つ選ぶ必要があると言うことである。
これら3つはファイルをどの様に開くかのみを定義している。
ファイルに書き込みを行いたい場合は別途O_APPEND
を呼び出す必要がある。
Permission
ここで指定するPermissionはLinuxなどのPermissionと同じ形式で指定する。
`go`でコマンドのフラグを扱う
golangでコマンドを作成した場合、フラグによって動作を分けたい場合がある。
この動作はflag
パッケージを使うことで可能である。
公式ドキュメント https://golang.org/pkg/flag
非フラグを受け取る
cmd 1 2 3
など、-hoge
でフラグを指定しないことも可能である。
この場合、ソース内では配列として受け取る。
package main import "flag" func main() { flag.Parse() flags := flag.Arg() //[]stringが返る。 }
フラグを使って受け取る。
cmd -flag somthing
と-flag
を指定してフラグを渡すこともかのである。
package main import "flag" func main() // flag.Int(flag_name, default_value, hlep_message) f := flag.Int("f", "0", "message") }
Dockerによるアプリケーション開発環境構築ガイド
Dcokerによる基本的なコマンド
Dockerコマンドのシーン毎の利用例
1. Dockerイメーシを取得しRunする。
- docker imageをpullする。 docker pull
- imageからconteinerをrunする。 docker run -d //demon化 -it //擬似TTY --name hoge ubuntu:16.04 bash
2.ターミナルからphpをインストールして、新しいイメージを作成する。
- 1で起動したコンテナに入る。docker exec -it //擬似TTYで接続します。(Docker内でコマンドの実行のみをしたい場合は不要?) hoge bash
- 起動したコンテナで色々作業をする。
- 上記の操作を反映したコンテナのイメージをcommitで作成する。docker commit hoge
- 作成したdocker imageにtagをつける。docker tag [作成されたID] smpledokcer1234/ubuntu_with_php:1_0
<疑問>
docker run -it
<-it
ってなんで必要なの? <答え> 作成したDcokerの標準入出力を中継してくれる擬似的なTTYというものを作成する。 これを指定しないと、docker exec -it hoge bash
などしてもthe input device is not a TTY
と言われて怒られる。
3.作成したイメージをファイルに出力して、一度手元から消した後にファイルを読み込んで復元
- imageをファイルに保存する。docker save -o /tmp/ubuntu_with_1_0 sampbledocker1234/ubuntu_with_php:1_0
- imageを一旦消す。 docker irm sampledocker1234/ubuntu_with_php:1_0
- loadコナンをを用いてファイルの読み込みを行う。docker load < /tmp/ubuntu_with_php_1_0
4.ローカルファイルをコンテナにコピー、逆にコンテナのファイルをローカルにコピーする
- ローカルマシーンのファイルをDockerにコピーする。touch samplefile | docker cp samplefile [dockerID]
- Dockerコンテナのファイルをローカルにコピーします。docker cp [dockerID]:samplefile /temp/
DockerfileでオリジナルのDcokerを作成する。
Docker CommitではOriginalのDocker Imageを元に任意の処理を行ったのちに、Imageを作成する事ができました。
しかし、この方法ではどのImageを使用してどの様な操作を行ったのかを後から確認するには大変です。
どのため、Dockerにはdocker build
というDcokerfileというファイルで定義した一連の手続きをコンテナイメージを作成する仕組みです。
Dockerfileとは
Dcokerfile
には下記を指定する事が可能です。
- Dcokerイメージの指定
- 必要なパッケージのインストール
- ファイルやディレクトリのコンテナ内のコピー
- ユーザアカウントの作成や任意のコマンドの実行
Dockerfileで使用できるコマンド
Dockerfileを記述するのに最低限必要なコマンドは下記の通りです。
コマンド | 意味 |
---|---|
FROM | ベースとなるDockerイメージを指定するコマンド |
ENV | 環境変数を設定するためのコマンド |
ARG | buildをする際に利用する引数を定義するコマンド。 デフォルト値を持つ事もできる。 buildコマンドからは --build-ages オプションにより利用する。 |
LABEL | Dockerイメージにメタデータを付与するためのコマンド |
RUM | shellの実行を行うためのコマンド |
SHELL | デフォルトのコマンドを設定するためのコマンド |
WORKDIR | 起点となるディレクトリを変更するためのコマンド。 この設定を行うとRUN, CMD, ENTRYPOINT COPY, ADDのコマンドで相対パスが使われた時はそのデフォルトを起点として解釈される。 |
ADD | ファイルやディレクトリおよび指定されたURLリソースをコンテナの指定されたパスに対してコピーするコマンド。 圧縮されている場合は解凍されてコピーされる。 |
COPY | ADDの解凍されずにcopyされる版 |
EXPOSE | コンテナがlistenするポート番号明示するためのコマンド。 あくまでも明示的に宣言するだけで実際に宣言しないとポートが開かない訳は無い。 ただし、実行時には正しく-pオプションにsてdockerホストとのポートを接続する必要はある。 |
ENTRYPOINT | コンテナ起動時に事項するコマンドを指定するコマンド |
CMD | ENTRYPOINTと同じ |
dockerでのポート
Docker内部にアプリをインストールした場合、そのアプリに対して通信を行う必要が出てくる。 この様な場合、docker内部のアプリと通信を可能にするために、ポートを設定する必要がある。
ポートの指定はdocker run -p [hostのIPを指定(ex: localhost)]:[host側のポートを指定]:[Docker側のポートを指定]
を使用すれば可能です。
例えば、ホスト側の80ポートに対してDockerの80ポートをバインドしたい場合は下記の通り設定を行う。
▶︎入力
docker run -d -p 80:80 sample:nginx
▶︎出力
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 4fb9e407daa6 sample:nginx "nginx -g 'daemon of…" 7 hours ago Up 7 hours 0.0.0.0:80->80/tcp
(追記予定)
※「Dockerによるアプリケーション開発環境構築ガイド」を読んで内容を自分なりにまとめたものです。