TIME_WAIT
_ sはありません通常、TCP接続が閉じられると、close()
が最初に呼び出される側のソケットは_TIME_WAIT
_状態のままになります。
ピアの1つがMacOS X(Lion)マシンである場合、Mac側でclose()
が最初に呼び出されると、Macでは_TIME_WAIT
_が_netstat -an
_によってリストされません。ただし、ソケットは実際には_TIME_WAIT
_状態にあるようです。これは、(を使用せずに)listen()
を再度呼び出そうとしているためです。ソケットオプション_SO_REUSEADDR
_)により、listen()
が失敗します。
2 * MSL(_sysctl net.inet.tcp.msl
_によって報告されたMac OS X Lionでの最大セグメントライフタイムは15秒)を待機すると、_TIME_WAIT
_状態がクリアされ、listen()
をエラーなしで再度呼び出すことができます。 。
_TIME_WAIT
_にソケットが表示されないのはなぜですか?
Pythonの2つの簡単なテストプログラムを次に示します。
サーバー
_#!/usr/bin/env python
import socket
Host = ''
PORT = 50007
l = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
l.bind((Host, PORT))
l.listen(1)
print("Listening on %d" % PORT)
(s, _) = l.accept()
print("Connected")
raw_input("Press <enter> to close...")
l.close()
s.close()
print("Closed")
_
クライアント
_#!/usr/bin/env python
import socket
import sys
Host = sys.argv[1]
PORT = 50007
print("Opening connection to server")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((Host, PORT))
raw_input("Press <enter> to close...")
s.close()
print("Closed")
_
サーバーとクライアントの両方を2つの異なるLinuxマシンで実行している場合、_<enter>
_を押してclose()
を呼び出すピアは、期待どおりに最初に_TIME_WAIT
_を取得します。
_$ ./server-timewait.py
Listening on 50007
Connected
Press <enter> to close...
Closed
$ netstat -an | grep 50007
tcp 0 0 172.16.185.219:50007 172.16.185.42:49818 TIME_WAIT
$
_
ピアの1つがMac(OS X Lionを実行している)の場合、Macで最初に閉じた後に_TIME_WAIT
_を実行すると、_netstat -an | grep 50007
_が表示されません。
これは答えではありませんが、誰かがこれからもっと掘り下げることができるかもしれません。
tcpdump -i lo0 -vv port 50007
## Press Enter at the server window
# Server send a FIN (note the flag)
23:33:04.283768 IP (tos 0x0, ttl 64, id 4134, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->2c9c)!)
localhost.50007 > localhost.56030: Flags [F.], cksum 0xfe28 (incorrect -> 0xeff9), seq 1, ack 1, win 9186, options [nop,nop,TS val 432165676 ecr 432157913], length 0
# Client send back ACK
23:33:04.283803 IP (tos 0x0, ttl 64, id 44906, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->8d57)!)
localhost.56030 > localhost.50007: Flags [.], cksum 0xfe28 (incorrect -> 0xd1a6), seq 1, ack 2, win 9186, options [nop,nop,TS val 432165676 ecr 432165676], length 0
# Server confirm the ACK is received
23:33:04.283812 IP (tos 0x0, ttl 64, id 18284, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->f555)!)
localhost.50007 > localhost.56030: Flags [.], cksum 0xfe28 (incorrect -> 0xd1a6), seq 2, ack 1, win 9186, options [nop,nop,TS val 432165676 ecr 432165676], length 0
## After this point, the server process is actually exit but client still running.
## It's strange that re-run server script gives "OSError: [Errno 48] Address already in use"
## and netstat shows this connection is in CLOSE_WAIT status
## Press Enter at the client window
# Client send a FIN to server
23:33:09.731728 IP (tos 0x0, ttl 64, id 51478, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->73ab)!)
localhost.56030 > localhost.50007: Flags [F.], cksum 0xfe28 (incorrect -> 0xbcb6), seq 1, ack 2, win 9186, options [nop,nop,TS val 432171035 ecr 432165676], length 0
# WTH!? Who send back this packet? The server process is closed!
23:33:09.731764 IP (tos 0x0, ttl 64, id 18754, offset 0, flags [DF], proto TCP (6), length 52, bad cksum 0 (->f37f)!)
localhost.50007 > localhost.56030: Flags [.], cksum 0xfe28 (incorrect -> 0xa7c7), seq 2, ack 2, win 9186, options [nop,nop,TS val 432171035 ecr 432171035], length 0