2012/04/04

python socket reset

明日こそは散髪に行こうと思っています!!

何がしたかったの? と聞かれてもマイッチングのですが
"python socket reset" で検索してました。
reset できるようになりたかったみたいです。
そんな質問には stackoverflow がさくっと答えてくれますよ

http://stackoverflow.com/questions/6439790/sending-a-reset-in-tcp-ip-socket-connection

SO_LINGER ってのを使えって書いてあるけど何じゃらほい。
ググるよ。

TCPメモ(Hishidama's TCP Memo)

ほー。SO_LINGER ってのを on で 0 に指定して close() しろと。
でも SO_LINGER って何じゃらほい? と思ってもう少し調べたけど、
結局 man に辿りついちゃうのよね。

Man page of SOCKET
SO_LINGER
SO_LINGER オプションを取得・設定する。引き数には linger 構造体を取る。
struct linger {
    int l_onoff;    /* linger active */
    int l_linger;   /* how many seconds to linger for */
};
有効になっていると、 close(2) や shutdown(2) は、そのソケットにキューイングされたメッセージがすべて送信完了するか、 linger (居残り) タイムアウトになるまで返らない。無効になっていると、 これらのコールはただちに戻り、クローズ動作はバックグラウンドで行われる。 ソケットのクローズを exit(2) の一部として行った場合には、残っているソケットの クローズ動作は必ずバックグラウンドに送られる。

  • SO_LINGER の設定無しに close とかすると後処理は kernel に任せられて SOCKET が何か WAIT になる
  • SO_LINGER が設定されてると TIMEOUT するか送信確認できるまで block する
  • 特に SO_LINGER が on で TIMEOUT が 0 だと

というわけでちょっと書いてみた:
import socket

addr = socket.getaddrinfo('www.google.com', 80)[0][4]
print(addr[0])
sock = socket.socket()
sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, b'\1\0\0\0\0\0\0\0')
sock.connect(addr)
sock.close()
実行してみた:
$ time ip_address=`python test.py`; echo $ip_address; netstat -tn | grep "$ip_address"
74.125.235.81
何も残らない。TIMEOUT も 1 にしてみた:
import socket

addr = socket.getaddrinfo('www.google.com', 80)[0][4]
print(addr[0])
sock = socket.socket()
sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, b'\1\0\0\0\1\0\0\0')
sock.connect(addr)
sock.close()
実行してみた:
$ ip_address=`python test.py`; echo $ip_address; netstat -tn | grep "$ip_address"
173.194.38.80
tcp        0      0 192.168.37.5:42359      173.194.38.80:80        TIME_WAIT  
残った。

TIMEOUT を設定すると RST じゃなくなる、のかな?
と思ったら違うか、TIMEOUT すると RST 投げるんだな、きっと。
ソース嫁ですと? ふへへ。

ちなみに、SO_LINGER で画像検索するとちょっと面白かったです。