molpako.py

もるぱこのブログです

[Go] TCP接続でハーフクローズを行う

概要

GoでTCPロキシーを書いていたら、接続先に書き込み完了を伝えるために、ハーフクローズが必要だった。メモ書きレベルだが、まとめておく。

この記事でしないこと

  • ACKとFINなどのパケットについての説明
  • ネットワークコネクション構造体のCloseメソッドについての説明
  • 検証作業

TCPのハーフクローズ

  • TCPは全二重通信である
  • 送受信の双方向からの切断が必要
  • 片側の切断をハーフクローズという

Go net.TCPConn

Go言語でネットワークプログラミングを行う場合、net.Conn インターフェースが一般的に使用される。しかし net.Conn は標準的なネットワークコネクションであるため、全二重通信に必要なハーフクローズに関するメソッドは含まれていない。

ハーフクローズが必要な場合は、net.TCPConnやnet.UnixConn構造体をそのまま扱う必要がある。

読み込み側のクローズ

読み込みの完了後 CloseRead を実行する。接続先から読み込みができなくなる。

func (c *TCPConn) CloseRead() error

書き込み側のクローズ

書き込みの完了後 CloseWrite を実行する。接続先には書き込みができなくなる。

func (c *TCPConn) CloseWrite() error

少しソースを追っかけてみると、shutdown(socket, SHUT_WR) を呼び出されていて、それによって、socketに対する書き込み側通信が閉じられる。という感じだった。(読み取り側も同様)

まとめ

ドキュメントにもある通り基本的にはCloseで済むパターンが多いと思う。しかし、何かしらの理由で片側通信だけをクローズしたいというときはCloseReadやCloseWriteメソッドを実行しハーフクローズすることが必要。