ポート番号_8000
_でソケット(サーバーソケット)をバインドしようとしました。それは私のために働き、仕事をしました。コードの最後で、ソケットも閉じます。次の瞬間、コードを再度実行すると、アドレスがすでに使用されていることがわかります。エラー値の意味strerror(errno);
を出力して、各ポイントでコードが適切に機能するかどうかを確認しました。ポートが空いているかどうかを確認するには、netstat
を使用してチェックしましたが、ポート番号_8000
_が空いていることがわかります。私には何度も起こりました。その後、さらに数秒間待機するたびに、再び動作を開始します。 C言語を使用しています。それで、彼は私のOSによるこの振る舞いの理由は何でしょうか。
さらに数秒後、コードを実行すると動作します。
_anirudh@anirudh-Aspire-5920:~/Desktop/testing$ Sudo ./a.out
Socket Creation: Success
File open: Success
Socket Bind: Address already in use
Socket Listen: Address already in use
^C
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ Sudo netstat -lntp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1348/lighttpd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 984/sshd
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 1131/cupsd
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 1211/mysqld
tcp6 0 0 :::22 :::* LISTEN 984/sshd
tcp6 0 0 ::1:631 :::* LISTEN 1131/cupsd
anirudh@anirudh-Aspire-5920:~/Desktop/testing$ Sudo ./a.out
Socket Creation: Success
File open: Success
Socket Bind: Address already in use
Socket Listen: Address already in use
^C
anirudh@anirudh-Aspire-5920:~/Desktop/testing$
_
私も同じ問題に遭遇しました。これは、ソケットへの接続を閉じているが、ソケット自体を閉じていないためです。ソケットはTIME_WAIT状態に入ることができます(すべてのデータが送信されたことを確認するために、TCP配信を保証します)) および解放に最大4分かかります 。
または、本当に詳細な/技術的な説明については、 このリンクを確認してください
確かにうんざりするかもしれませんが、それを回避する方法はありません。バグではありません。
質問がされてからしばらく経ちましたが、解決策を見つけることができました。
int sockfd;
int option = 1;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option));
これにより、すぐに再利用できるソケットが設定されます。
これが「間違っている」場合は謝罪します。ソケットの経験があまりない
次のようなnetstatを試してください:netstat -ntp
、-l
なし。 TIME_WAIT
状態のtcp接続が表示されます。
既に述べたように、ソケットはおそらくTIME_WAIT
状態に入ります。この問題はThomas A. Finehere で説明されています。
要約すると、ソケットを閉じるプロセスは次の図に従います。
Thomas言います:
上の図を見ると、リモートエンドが閉鎖を開始した場合、
TIME_WAIT
を回避できることが明らかです。したがって、サーバーは最初にクライアントを閉じることで問題を回避できます。クライアントがいつ閉じるべきかを知るように、アプリケーションプロトコルを設計する必要があります。サーバーは、クライアントからのEOFに応答して安全に閉じることができますが、EOF多くの場合、サーバーが閉じる前に数秒待つだけで十分です。
SO_REUSEADDR
の使用は、インターネットでは一般的に推奨されていますが、Thomasを追加します。
奇妙なことに、
SO_REUSEADDR
を使用すると、実際にはより困難な「既に使用されているアドレス」エラーにつながる可能性があります。SO_REUSADDR
は、TIME_WAIT
でスタックしているポートを使用することを許可しますが、そのポートを使用して、最後に接続した場所への接続を確立することはできません。何?ローカルポート1010を選択し、foobar.comポート300に接続し、ローカルで閉じて、そのポートをTIME_WAIT
のままにしておきます。ローカルポート1010をすぐに再利用して、foobar.com
ポート300以外のどこにでも接続できます。
入力するだけ
unlink [SOCKET NAME]
端末では、エラーはもう存在しないはずです。
この質問に対するicfantvの答えでさえすでに完璧です、私はまだ私のテストでより多くの発見を持っています。
リスニングステータスのみのサーバーソケットとして、リスニングステータスのみで、クライアントサイドからのリクエストとデータの取得を受け入れますが、データ送信アクションはありません。停止した後でもサーバーを一度に再起動できました。ただし、サーバー側でクライアントへのデータ送信アクションが発生した場合、同じサービス(同じポート)の再起動で次のエラーが発生します:(アドレスは既に使用されています)。
これはTCP/IPの設計原理が原因だと思います。サーバーがクライアントにデータを送り返すとき、データ送信が成功することを確認する必要があります。これを行うには、OS(Linux)は、サーバーアプリケーションがこのソケットを閉じた場合でも接続を監視する必要があります。しかし、カーネルソケットデザイナーはこの問題を改善できると今でも信じています。
私が受け取ったエラーは:
cockpit.socket: Failed to listen on sockets: Address already in use
私が発見した修正は:
/ usr/lib/systemd/system/cockpitサービスで次の行を変更しました:
#ExecStartPre=/usr/sbin/remotectl certificate --ensure --user=root --group=cockpit-ws --selinux-type=etc_t
に:
#ExecStartPre=/usr/sbin/remotectl certificate --ensure --user=root --group=cockpit-ws
あなたが見ることができるように、私はselinuxに関する議論を取り出してから実行しました:
systemctl daemon-reload
systemctl start cockpit.service
それから私は閲覧しました:
自己署名証明書を受け入れ、コックピットに正常にログインし、正常に使用することができました。
これはすべてFedora25マシン上にあります。 90_90ポートは既にfirewall-cmd
を使用して追加されていました
AF_UNIXの場合、call unlink(パス)を使用できます。 「サーバー」アプリのclose()ソケットの後