このリンクを確認してください
http://www.toptip.ca/2010/02/linux-eaddrnotavail-address-not.html
編集 :はい、もっと追加するつもりでしたが、緊急のためにそこでカットしなければなりませんでした
再接続を試みる前にソケットを閉じましたか?閉じると、ソケットペア (ip/port) が解放されたことがシステムに通知されます。
追加の項目もご覧ください:
- ローカル ポートが指定されたリモート IP とポートに既に接続されている場合 (つまり、同一のソケット ペアが既に存在する場合)、このエラーが発生します (以下のバグ リンクを参照してください)。
- ローカルのものではないソケットアドレスをバインドすると、このエラーが発生します。マシンの IP アドレスが 127.0.0.1 と 1.2.3.4 で、1.2.3.5 にバインドしようとすると、このエラーが発生します。
- EADDRNOTAVAIL:指定されたアドレスがリモート マシンで利用できないか、名前構造体のアドレス フィールドがすべてゼロです。
あなたに似たバグとリンクしてください (答えは一番下にあります)
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4294599
あなたのソケットは基本的に TCP 内部状態の 1 つでスタックしているようで、再接続の遅延を追加すると、そのバグ レポートで行われたように、問題が解決する可能性があります。
使用可能な一時ポートの数を変更したくない場合 (David の提案による)、または理論上の最大数よりも多くの接続が必要な場合は、使用中のポートの数を減らす方法が他に 2 つあります。ただし、これらはさまざまな程度で TCP 標準に違反しているため、注意して使用する必要があります。
最初は SO_LINGER
をオンにすることです TCP
を強制的に 0 秒のタイムアウトで stack を使用して RST パケットを送信し、接続状態をフラッシュします。ただし、微妙な点が 1 つあります。shutdown
を呼び出す必要があります。 close
する前にソケットファイル記述子に 、 FIN
を送信するチャンスがあるように RST
の前のパケット パケット。したがって、コードは次のようになります:
shutdown(fd, SHUT_RDWR);
struct linger linger;
linger.l_onoff = 1;
linger.l_linger = 0;
// todo: test for error
setsockopt(fd, SOL_SOCKET, SO_LINGER,
(char *) &linger, sizeof(linger));
close(fd);
FIN
パケットは RST
で並べ替えられます
詳細については、TCP オプション SO_LINGER (ゼロ) - 必要な場合を参照してください。 (実験的には、 setsockopt
をどこに設定しても問題ないようです .)
2 つ目は、SO_REUSEADDR
を使用することです。 および明示的な bind
(あなたがクライアントであっても)、Linux は実行時に一時的なポートを再利用できるようになります。 しなければならないことに注意してください bind
を使用 INADDR_ANY
で およびポート 0
、それ以外の場合は SO_REUSEADDR
尊重されません。コードは次のようになります:
int opts = 1;
// todo: test for error
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
(char *) &opts, sizeof(int));
struct sockaddr_in listen_addr;
listen_addr.sin_family = AF_INET;
listen_addr.sin_port = 0;
listen_addr.sin_addr.s_addr = INADDR_ANY;
// todo: test for error
bind(fd, (struct sockaddr *) &listen_addr, sizeof(listen_addr));
// todo: test for addr
// saddr is the struct sockaddr_in you're connecting to
connect(fd, (struct sockaddr *) &saddr, sizeof(saddr));
netstat -an | grep -e tcp -e udp | wc -l
のように、TCP 接続の内部カーネル データ構造を飽和させてしまうため、このオプションはあまり適していません。 .ただし、これが発生するまでポートの再利用は開始されません。
これは、0 などの無効なポートが指定された場合にも発生する可能性があります。