2017-03-28 5 views
2

私のLinux(4.10.3)システムでは、単純なCベースのサーバー プログラムで作業しているときに、何か変わったことに気付きました。私は間違って listen()(サーバプロセスから)を2回呼び出すことになりました。 は、以前はbind()と呼ばれていました。私は両方のリッスンコール がエラーなしで成功したことに気づいた。実際には、私が聞いてくれる電話番号がどれくらいあるのかは関係ありません。すべてのコールを聞いて成功します。ソケットで複数回呼び出されたときのリッスン - 予想される動作?

最初の呼び出しが失敗した後にすべての呼び出しが呼び出されることを期待していました。 とEADDRINUSEです。何か不足していますか? Linux/POSIXのmanページは はこれについて何も言わないようです。

https://www.mkssoftware.com/docs/man3/listen.3.asp

アプリケーションは(聞く呼び出すことができます)一度、同じソケット上より:私は、以下のウェブページ上 この動作に関する一つの基準を見つけました。 これは、リッスンソケット の現在のバックログを更新する効果があります。新しいバックログ の値よりも保留中の接続が多い場合は、保留中の過剰な接続がリセットされ、破棄されます。

これがLinuxにも当てはまるかどうかは不明です。そして、私の質問は次のようになります: 同じソケットで何度も何度も聞いても何が起こるのですか? 同じプロセスですか? (明らかにユーザー空間に目に見える副作用はありませんが、 ですが、Linuxカーネルはカーネル空間で特別なことをしていますか?)

ありがとう。

+0

私が読んだ[POSIX spec for 'listen'](http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)は、この場合の動作を指定していない移植性のあるコードはそれを避けるべきです。 – zwol

+0

私はEADDRINUSEを期待しません。これは前の 'bind()'のステップで起こります。たぶんEINVAL。 – EJP

+0

@zwol:そうです、移植性のあるプログラムはそれを避けるべきです。私は、Linuxカーネルが何をするのか不思議に思っていました。 – userRG

答えて

2

Linuxカーネルは、新しいバックログ値を使用してバックログキューの長さを調整しますが、将来の接続要求に対してのみ調整します。待ち行列内に既に保留中の接続は破棄されません。

listen()への2回目以降の呼び出しは、ソケットが間違ったタイプ(SOCK_STREAMではなく)でないか、間違った状態(特定のピアにすでに接続されているか、すでに閉鎖のプロセス)。

+0

ありがとう、@ギル、それは最も可能性の高い説明のようです。私はカーネルを通してこれをトレースしようとしています。 – userRG

関連する問題