Socketの作成で「Address already in use: connect」が発生する
Windows XP環境で、次のコードを実行すると、
for ( int i = 0 ; i < 20000; i++ ) { System.out.println( i ); Socket s = null; try { s = new Socket("hogehoge.com", 80); } finally { if (s != null) { s.close(); } } }
4000回目くらいで以下のエラーになる。
.... 3958 3959 3960 3961 3962 3963 Exception in thread "main" java.net.BindException: Address already in use: connect at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333) at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195) at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366) at java.net.Socket.connect(Socket.java:516) at java.net.Socket.connect(Socket.java:466) at java.net.Socket.<init>(Socket.java:366) at java.net.Socket.<init>(Socket.java:179) ....
上記コードをLinux環境で実行した場合、エラーは発生しない。(20000回まで確認)
原因
Windowsにおけるソケットの最大値とTIME_WAITの時間を修正しようより、WindowsXPでは、「ソケットの最大数」が決まっており(デフォルトは5000)、さらにcloseしたソケットも一定期間は使えないらしい。なので、上みたいなコードを書くとあっという間に枯渇する。
補足:Windows Server 2003ではどうなの
- Windows Server 2003でも「ソケットの最大数」の初期値は5000。
- 「Smart TCP Port Allocation」とかいう機能が実装されているので、XPとは挙動が違うかも。