TCP通信ネタ
TCP関係備忘録
自分Github
https://github.com/KosigayaSuguru/sample-project/tree/master/test-socket
※細かい挙動の確認は↑の README.md 参照
closeされたsocketへの動作について
socket.close()はFINの送信を行っているのだと思われる。
実際にclose()を実行すると、close()した時点でTCPのステータスが、
自分:FIN_WAIT2
相手:CLOSE_WAIT
になる。
ゆえに、相手側はwrite()してもエラーにならない。(CLOSE_WAITなので、相手側的には通信を終わらせるつもりがない。)
※でも2回witeするとエラーになる。。※※自分github参照
read()した場合、終端が返ってくる。(相手が通信を終わらせるつもりなのがここで分かる)
相手がreadブロックしている際にclose()以外(つまりFINの送信以外)の方法で強制終了させると、read側でそれに応じた例外が出る。
close()実行後、相手がwrite()した場合、TCP的にはそこで通信が終了している。
自分FIN_WAIT2,相手CLOSE_WAITの状態から、自分LISTENINGのみにかわる。
相手がもう一度writeすると、相手側で例外が発生する。
自分githubのまとめも参照。
Socket
通信相手が切ったことは検知できないので、定期的に監視の電文を送る監視スレッドが必要。
Stream
Writerを使うと扱いの単位が文字単位になり、バイトを使った厳密な操作ができないので注意。
InputStream.read()でブロックされていることに気がつかず、躓いてしまった
http://redfreshet.com/2015/11/01/java_inputstream_read/
※readブロックを解除するのは通信相手のflush()かclose()らしい(flush(の方は未確認))
Javaの実装の注意点
http://majimem.hatenablog.com/entry/2014/06/11/165732
http://axe1lyze.blogspot.jp/2011/08/java.html?m=1
InputStreamをOutputStreamより先にgetする(もしくはその逆)と、良いことあるかも。(read()が動くようになるかも。。)
Javaの実装の注意点2
close()した後、相手との通信状態によっては、readブロックの部分で例外が吐かれる可能性がある。
close()がコールされたことを管理するフラグを持たせ、closeのフラグが立っている場合は例外の出力を抑止するなどの小技が必要。。