移植性の素晴らしい世界へようこそ...むしろそれの欠如。これら2つのオプションの詳細な分析を開始する前に、さまざまなオペレーティングシステムがそれらをどのように処理するかを詳しく見ていく前に、BSDソケット実装がすべてのソケット実装の母であることに注意してください。基本的に、他のすべてのシステムは、ある時点(または少なくともそのインターフェース)でBSDソケットの実装をコピーし、独自に進化させ始めました。もちろん、BSDソケットの実装も同時に進化したため、それをコピーしたシステムには、以前にそれをコピーしたシステムでは欠けていた機能が追加されました。BSDソケットの実装を理解することは、他のすべてのソケットの実装を理解するための鍵となるため、BSDシステムのコードを作成する必要がない場合でも、このソケットの実装について読む必要があります。
これら2つのオプションを見る前に知っておくべき基本事項がいくつかあります。TCP / UDP接続は、次の5つの値のタプルで識別されます。
{<protocol>, <src addr>, <src port>, <dest addr>, <dest port>}
これらの値の一意の組み合わせは、接続を識別します。その結果、2つの接続が同じ5つの値を持つことはできません。そうしないと、システムはこれらの接続を区別できなくなります。
socket()
関数を使用してソケットが作成されると、ソケットのプロトコルが設定されます。送信元アドレスとポートはbind()
関数で設定されます。connect()
関数で宛先アドレスとポートを設定します。UDPはコネクションレス型プロトコルであるため、UDPソケットは接続せずに使用できます。しかし、それらを接続することが許可されており、場合によっては、コードや一般的なアプリケーション設計にとって非常に有利です。コネクションレスモードでは、データが最初に送信されたときに明示的にバインドされなかったUDPソケットは、バインドされていないUDPソケットが(応答)データを受信できないため、通常、システムによって自動的にバインドされます。バインドされていないTCPソケットについても同様です。接続される前に自動的にバインドされます。
明示的にソケットをバインドする場合0
、「任意のポート」を意味するポートにバインドすることが可能です。ソケットは実際には既存のすべてのポートにバインドできないため、その場合、システムは特定のポート自体を選択する必要があります(通常、事前定義された、OS固有のソースポートの範囲から)。送信元アドレスにも同様のワイルドカードが存在し、「任意のアドレス」にすることができます(0.0.0.0
IPv4および::
IPv6の場合)。ポートの場合とは異なり、ソケットは実際には「すべてのローカルインターフェースのすべての送信元IPアドレス」を意味する「任意のアドレス」にバインドできます。ソケットが後で接続される場合、ソケットは接続できないと同時にローカルIPアドレスにバインドできないため、システムは特定の送信元IPアドレスを選択する必要があります。宛先アドレスとルーティングテーブルの内容に応じて、システムは適切な送信元アドレスを選択し、「any」バインディングを選択した送信元IPアドレスへのバインディングに置き換えます。
デフォルトでは、送信元アドレスと送信元ポートの同じ組み合わせに2つのソケットをバインドすることはできません。送信元ポートが異なる限り、送信元アドレスは実際には無関係です。バインドsocketA
にA:X
してsocketB
までB:Y
、どこA
とB
アドレスであり、X
およびY
ポートで、限りとして、常に可能であるX != Y
が成り立ちます。ただし、であってもX == Y
、A != B
当てはまる限りバインディングは可能です。例えば、socketA
FTPサーバプログラムに属し、にバインドされている192.168.0.1:21
とsocketB
、別のFTPサーバプログラムに属し、にバインドされ10.0.0.1:21
、両方のバインディングが成功します。ただし、ソケットはローカルで「任意のアドレス」にバインドされる可能性があることに注意してください。ソケットがバインドされている場合0.0.0.0:21
、既存のすべてのローカルアドレスに同時にバインドされます。その場合、既存のすべてのローカルIPアドレスと競合21
するため、バインドしようとする特定のIPアドレスに関係なく、他のソケットをポートにバインドできません0.0.0.0
。
これまで述べたことは、すべての主要なオペレーティングシステムでほぼ同じです。アドレスの再利用が機能するようになると、OS固有のものが始まります。先に述べたように、それはすべてのソケット実装の母であるので、BSDから始めます。
BSD
SO_REUSEADDR
SO_REUSEADDR
バインドする前にソケットでが有効になっている場合、送信元アドレスとポートのまったく同じ組み合わせにバインドされている別のソケットとの競合がない限り、ソケットは正常にバインドできます。今、あなたはそれが以前とどのように違うのか疑問に思うかもしれませんか?キーワードは「完全に」です。SO_REUSEADDR
主に、競合を検索するときのワイルドカードアドレス(「任意のIPアドレス」)の処理方法を変更します。
せずにSO_REUSEADDR
結合、socketA
に0.0.0.0:21
して、結合socketB
する192.168.0.1:21
(エラーで失敗しますEADDRINUSE
)、0.0.0.0手段「任意のローカルIPアドレス」以来、したがって、すべてのローカルIPアドレスがこのソケットで使用されているとみなされ、これは、192.168.0.1
あまりにも、。でSO_REUSEADDR
、それがあるため、成功する0.0.0.0
と192.168.0.1
されている正確ではない同じアドレス、一つは、すべてのローカルアドレスにはワイルドカードであり、もう一つは非常に特定のローカルアドレスです。上記のステートメントは、どの順序socketA
でsocketB
バインドされているかに関係なく当てはまることに注意してください。SO_REUSEADDR
それなしでは常に失敗し、SO_REUSEADDR
常に成功します。
概要をわかりやすくするために、ここに表を作成し、可能なすべての組み合わせをリストしてみましょう。
SO_REUSEADDR socketA socketB結果
-------------------------------------------------- -------------------
ON / OFF 192.168.0.1:21 192.168.0.1:21エラー(EADDRINUSE)
ON / OFF 192.168.0.1:21 10.0.0.1:21 OK
ON / OFF 10.0.0.1:21 192.168.0.1:21 OK
オフ0.0.0.0:21 192.168.1.0:21エラー(EADDRINUSE)
オフ192.168.1.0:21 0.0.0.0:21エラー(EADDRINUSE)
オン0.0.0.0:21 192.168.1.0:21 OK
オン192.168.1.0:21 0.0.0.0:21 OK
ON / OFF 0.0.0.0:21 0.0.0.0:21エラー(EADDRINUSE)
上の表は、socketA
がに指定されたアドレスに既に正常にバインドされていることを前提としていますsocketA
。その後socketB
、作成され、SO_REUSEADDR
設定されるかどうかにかかわらず、最後にに指定されたアドレスにバインドされsocketB
ます。Result
のバインド操作の結果ですsocketB
。最初の列がON/OFF
である場合、の値はSO_REUSEADDR
結果とは無関係です。
わかりました、SO_REUSEADDR
ワイルドカードアドレスに影響があります。それでも、それがもたらす効果だけではありません。ほとんどの人がSO_REUSEADDR
そもそもサーバープログラムで使用する理由でもある別のよく知られている効果があります。このオプションの他の重要な使用法については、TCPプロトコルがどのように機能するかをさらに詳しく調べる必要があります。
ソケットには送信バッファがあり、send()
関数の呼び出しが成功した場合でも、要求されたデータが実際に実際に送信されたことを意味するのではなく、データが送信バッファに追加されたことを意味するだけです。UDPソケットの場合、データはすぐではないにせよ通常はすぐに送信されますが、TCPソケットの場合、送信バッファーにデータを追加してから、TCP実装が実際にそのデータを送信するまでに比較的長い遅延が生じる可能性があります。その結果、TCPソケットを閉じても、まだ送信されていない保留中のデータが送信バッファに残っている可能性がありますが、コードはそれを送信済みと見なします。send()
呼び出しは成功しました。TCP実装が要求時にすぐにソケットを閉じていた場合、このデータはすべて失われ、コードはそれについてさえ知りません。TCPは信頼できるプロトコルであると言われており、そのようにデータを失うことはあまり信頼できません。そのため、まだ送信するデータがあるソケットは、TIME_WAIT
閉じるときに呼び出される状態になります。その状態では、保留中のすべてのデータが正常に送信されるまで、またはタイムアウトに達するまで待機します。この場合、ソケットは強制的に閉じられます。
カーネルがソケットを閉じるまでに待機する時間は、まだデータが処理中かどうかに関係なく、リンガータイムと呼ばれます。リンガー時間(2分あなたは多くのシステム上で見つける共通の値である)かなり長いほとんどのシステムで、デフォルトでは、グローバル設定可能です。またSO_LINGER
、タイムアウトを短くしたり長くしたり、完全に無効にするために使用できるソケットオプションを使用して、ソケットごとに構成することもできます。ただし、TCPソケットを正常に閉じることは少し複雑なプロセスであり、2、3のパケットの送信と送信(および失われた場合に備えてこれらのパケットを再送信する)とこの全体のクローズプロセスが含まれるため、完全に無効にすることは非常に悪い考えです。リンガータイムによっても制限されます。残存を無効にすると、ソケットは処理中のデータを失うだけでなく、正常にではなく常に強制的に閉じられる可能性があります。これは通常は推奨されません。TCP接続が正常に閉じられる方法の詳細は、この回答の範囲を超えています。詳しく知りたい場合は、このページをご覧になることをお勧めします。またSO_LINGER
、で残留を無効にした場合でも、明示的にソケットを閉じずにプロセスが停止すると、BSD(および場合によっては他のシステム)は残留し、設定した内容を無視します。これは、たとえば、コードが単に呼び出す場合に発生しますexit()
(非常に小さく単純なサーバープログラムではかなり一般的です)またはプロセスがシグナルによって強制終了されます(これには、不正なメモリアクセスが原因で単にクラッシュする可能性が含まれます)。したがって、すべての状況でソケットが残存しないようにするためにできることはありません。
問題は、システムが状態のソケットをどのように処理するTIME_WAIT
かです。SO_REUSEADDR
が設定されていない場合、状態のソケットはTIME_WAIT
まだ送信元アドレスとポートにバインドされていると見なされ、新しいソケットを同じアドレスとポートにバインドしようとすると、ソケットが実際に閉じられるまで失敗します。設定されたリンガータイムとして。したがって、ソケットを閉じた直後にソケットのソースアドレスを再バインドできるとは期待しないでください。ほとんどの場合、これは失敗します。ただし、SO_REUSEADDR
バインドしようとしているソケットにが設定されている場合、同じアドレスとポートにバインドされている別のソケットTIME_WAIT
すべてがすでに「半分死んでいる」後は無視され、ソケットはまったく同じアドレスに問題なくバインドできます。その場合、他のソケットがまったく同じアドレスとポートを持つ可能性があるという役割はありません。TIME_WAIT
状態にある瀕死のソケットとまったく同じアドレスとポートにソケットをバインドすると、他のソケットがまだ「機能している」場合、予期しない、通常は望ましくない副作用が発生する可能性がありますが、これはこの回答の範囲を超えており、幸い、これらの副作用は実際にはかなりまれです。
最後に知っておくべきことが1つありますSO_REUSEADDR
。バインドしたいソケットでアドレスの再利用が有効になっている限り、上記のすべてが機能します。すでにバインドされているか、TIME_WAIT
状態にある他のソケットも、バインド時にこのフラグが設定されている必要はありません。バインドが成功するか失敗するかを決定するコードはSO_REUSEADDR
、bind()
呼び出しに供給されるソケットのフラグのみを検査し、検査される他のすべてのソケットでは、このフラグは調べられません。
SO_REUSEPORT
SO_REUSEPORT
ほとんどの人が期待SO_REUSEADDR
することです。基本的に、以前にバインドされたすべてのソケットもバインドされる前に設定されていればSO_REUSEPORT
、任意の数のソケットをまったく同じ送信元アドレスとポートにバインドできます。アドレスとポートにバインドされている最初のソケットが設定されていない場合、他のソケットが設定されているかどうかに関係なく、最初のソケットが再度バインディングを解放するまで、他のソケットをまったく同じアドレスとポートにバインドすることはできません。コード処理の場合とは異なり、現在バインドされているソケットが設定されていることを確認するだけでなく、バインド時に競合するアドレスとポートを持つソケットが設定されていることも確認します。SO_REUSEPORT
SO_REUSEPORT
SO_REUSEPORT
SO_REUESADDR
SO_REUSEPORT
SO_REUSEPORT
SO_REUSEPORT
SO_REUSEPORT
は意味しませんSO_REUSEADDR
。つまり、SO_REUSEPORT
バインドされたときにソケットがSO_REUSEPORT
設定されておらず、まったく同じアドレスとポートにバインドされたときに別のソケットが設定されている場合、バインドは失敗しますが、これは予想されますが、他のソケットがすでに停止している場合も失敗します。であるTIME_WAIT
状態。ソケットを同じTIME_WAIT
状態の別のソケットと同じアドレスとポートにバインドできるようにするには、SO_REUSEADDR
そのソケットに設定するか、バインドする前に両方のソケットにSO_REUSEPORT
設定しておく必要があります。もちろん、ソケットにSO_REUSEPORT
との両方を設定できSO_REUSEADDR
ます。
SO_REUSEPORT
それ以降に追加されたこと以外に言うべきことはそれほど多くありません。そのためSO_REUSEADDR
、このオプションが追加される前にBSDコードを「フォーク」した他のシステムの多くのソケット実装ではそれが見つかりません。このオプションの前に、BSDで2つのソケットをまったく同じソケットアドレスにバインドする方法。
Connect()EADDRINUSEを返しますか?
ほとんどの人bind()
はエラーEADDRINUSE
で失敗する可能性があることを知っていますが、アドレスの再利用を試し始めるconnect()
と、そのエラーで失敗する奇妙な状況に遭遇する場合もあります。どうすればいいの?どうすれば、connectがソケットに追加したリモートアドレスを既に使用できますか?複数のソケットをまったく同じリモートアドレスに接続することはこれまで問題にならなかったので、ここで何が問題になっていますか?
返信の一番上で述べたように、接続は5つの値のタプルによって定義されます。覚えていますか?また、これらの5つの値は一意である必要があります。そうしないと、システムは2つの接続を区別できなくなります。まあ、アドレスの再利用により、同じプロトコルの2つのソケットを同じソースアドレスとポートにバインドできます。つまり、これらの5つの値のうち3つは、これら2つのソケットですでに同じです。これらのソケットの両方を同じ宛先アドレスとポートにも接続しようとすると、2つの接続されたソケットが作成され、そのタプルは完全に同一になります。これは、少なくともTCP接続では機能しません(UDP接続は実際の接続ではありません)。2つの接続のどちらか一方にデータが到着した場合、システムはデータがどの接続に属しているかを判別できませんでした。
したがって、同じプロトコルの2つのソケットを同じ送信元アドレスとポートにバインドし、両方を同じ宛先アドレスとポートに接続しようとconnect()
すると、実際に失敗し、EADDRINUSE
接続しようとする2番目のソケットのエラーが発生します。つまり、 5つの値の同じタプルを持つソケットはすでに接続されています。
マルチキャストアドレス
ほとんどの人は、マルチキャストアドレスが存在するという事実を無視しますが、存在します。ユニキャストアドレスは1対1の通信に使用されますが、マルチキャストアドレスは1対多の通信に使用されます。ほとんどの人はIPv6について知ったときにマルチキャストアドレスに気づきましたが、この機能がパブリックインターネットで広く使用されることはなかったにもかかわらず、IPv4にもマルチキャストアドレスが存在しました。
SO_REUSEADDR
複数のソケットを送信元マルチキャストアドレスとポートのまったく同じ組み合わせにバインドできるようにするための、マルチキャストアドレスの変更の意味。つまり、マルチキャストアドレスの場合SO_REUSEADDR
はSO_REUSEPORT
、ユニキャストアドレスの場合とまったく同じように動作します。実際には、コードの扱いSO_REUSEADDR
とSO_REUSEPORT
マルチキャストアドレスのために同一の、あなたはそれを言ってもいい手段がSO_REUSEADDR
暗示SO_REUSEPORT
すべてのマルチキャストアドレスおよび他の方法でラウンドのために。
FreeBSD / OpenBSD / NetBSD
これらはすべて、元のBSDコードのかなり遅いフォークです。そのため、3つすべてがBSDと同じオプションを提供し、BSDと同じように動作します。
macOS(MacOS X)
中核となるmacOSは、BSDコード(BSD 4.3)の比較的遅いフォークに基づいた、「Darwin」という名前のBSDスタイルのUNIX であり、後で(現時点では)FreeBSDと再同期されましたMac OS 10.3リリース用の5つのコードベース。これにより、AppleはPOSIXに完全に準拠できるようになります(macOSはPOSIX認定済みです)。コア(「Mach」)にマイクロカーネルがあるにもかかわらず、残りのカーネル(「XNU」)は基本的に単なるBSDカーネルであり、そのためmacOSはBSDと同じオプションを提供し、それらもBSDと同じように動作します。
iOS / watchOS / tvOS
iOSは、わずかに変更およびトリミングされたカーネル、ユーザースペースのツールセットを多少取り除いた、わずかに異なるデフォルトフレームワークセットを備えた単なるmacOSフォークです。watchOSとtvOSはiOSフォークであり、さらに細分化されています(特にwatchOS)。私の知る限り、それらはすべてmacOSとまったく同じように動作します。
Linux
Linux <3.9
Linux 3.9以前は、オプションのみがSO_REUSEADDR
存在していました。このオプションの動作は、BSDとほぼ同じですが、2つの重要な例外があります。
リスニング(サーバー)TCPソケットが特定のポートにバインドSO_REUSEADDR
されている限り、そのポートをターゲットとするすべてのソケットのオプションは完全に無視されます。同じポートに2番目のソケットをバインドすることは、BSDでもSO_REUSEADDR
設定せずに可能だった場合にのみ可能です。たとえば、ワイルドカードアドレスにバインドしてから、より具体的なアドレスまたはその逆にバインドすることはできません。BSDでは、両方を設定できますSO_REUSEADDR
。あなたができることは、常に許可されているので、同じポートと2つの異なる非ワイルドカードアドレスにバインドできることです。この点で、LinuxはBSDよりも制限的です。
2番目の例外は、クライアントソケットの場合、SO_REUSEPORT
バインドされる前に両方にこのフラグが設定されている限り、このオプションの動作はBSDとまったく同じです。これを許可する理由は、さまざまなプロトコルで複数のソケットを同じUDPソケットアドレスに正確にバインドできることが重要でありSO_REUSEPORT
、3.9以前は存在しなかっSO_REUSEADDR
たため、そのギャップを埋めるためにの動作がそれに応じて変更されたためです。 。その点では、LinuxはBSDよりも制限が少ないです。
Linux> = 3.9
Linux 3.9では、SO_REUSEPORT
Linuxにもオプションが追加されました。このオプションはBSDのオプションとまったく同じように動作し、バインドする前にすべてのソケットでこのオプションが設定されている限り、まったく同じアドレスとポート番号にバインドできます。
ただし、SO_REUSEPORT
他のシステムとの違いは2つあります。
「ポートハイジャック」を防ぐには、特別な制限が1つあります。同じアドレスとポートの組み合わせを共有するすべてのソケットは、同じ実効ユーザーIDを共有するプロセスに属している必要があります。したがって、あるユーザーが別のユーザーのポートを「盗む」ことはできません。これは、欠けているSO_EXCLBIND
/ SO_EXCLUSIVEADDRUSE
フラグをいくらか補うための特別な魔法です。
さらに、カーネルはSO_REUSEPORT
、他のオペレーティングシステムにはないソケットに対して「特別な魔法」を実行します。UDPソケットの場合は、データグラムを均等に分散しようとし、TCPリスニングソケットの場合は、着信接続要求(を呼び出すことで受け入れられるaccept()
)を分散しようとします。同じアドレスとポートの組み合わせを共有するすべてのソケットにわたって均等に。したがって、アプリケーションは複数の子プロセスで同じポートを簡単に開き、それを使用SO_REUSEPORT
して非常に安価なロードバランシングを取得できます。
アンドロイド
Androidシステム全体はほとんどのLinuxディストリビューションと多少異なりますが、コアではわずかに変更されたLinuxカーネルが機能するため、Linuxに適用されるすべてのものがAndroidにも適用されるはずです。
ウィンドウズ
WindowsはSO_REUSEADDR
オプションのみを認識し、はありませんSO_REUSEPORT
。設定SO_REUSEADDR
の設定のように、Windowsの振る舞いでソケットにSO_REUSEPORT
し、SO_REUSEADDR
一つの例外を除いて、BSDソケット上:付きソケットSO_REUSEADDR
常にすでにバインドされたソケットとまったく同じ送信元アドレスとポートにバインドすることができ、他のソケットは、このオプションを持っていなかった場合でも、バインドされたときに設定されます。この動作は、アプリケーションが別のアプリケーションの接続されたポートを「盗む」ことを可能にするため、多少危険です。言うまでもなく、これはセキュリティに大きな影響を与える可能性があります。Microsoftは、これが問題になる可能性があることを認識し、別のソケットオプションを追加しましたSO_EXCLUSIVEADDRUSE
。設定SO_EXCLUSIVEADDRUSE
ソケットでは、バインディングが成功した場合、送信元アドレスとポートの組み合わせがこのソケットによって排他的に所有され、他のソケットがそれらにバインドできないことを確認しますSO_REUSEADDR
。
フラグSO_REUSEADDR
とSO_EXCLUSIVEADDRUSE
Windowsでの動作、バインド/再バインドへの影響の詳細については、Microsoftは、返信の上部にある私のテーブルと同様のテーブルを提供してくれました。このページにアクセスして、少し下にスクロールしてください。場合は、実際に3つのテーブル、最初のショー古い動作(前のWindows 2003)、二番目の動作(Windows 2003およびアップ)と第3の1つのショーのWindows 2003以降でどのように行動に変化があったbind()
コールがで作られています別のユーザー。
Solaris
SolarisはSunOSの後継です。SunOSはもともとBSDのフォークに基づいていましたが、SunOS 5以降はSVR4のフォークに基づいていましたが、SVR4はBSD、System V、およびXenixのマージなので、ある程度までSolarisもBSDフォークであり、かなり早いもの。その結果、Solarisは知っているだけでSO_REUSEADDR
、ありませんSO_REUSEPORT
。SO_REUSEADDR
振る舞うほとんど同じ、それはBSDの場合と同様。私が知る限りSO_REUSEPORT
、Solaris と同じ動作をする方法はありません。つまり、2つのソケットをまったく同じアドレスとポートにバインドすることはできません。
Windowsと同様に、Solarisにはソケットに排他的バインディングを与えるオプションがあります。このオプションの名前はSO_EXCLBIND
です。このオプションをバインドする前にソケットで設定SO_REUSEADDR
した場合、2つのソケットのアドレスの競合がテストされても、別のソケットで設定しても効果はありません。例えば場合は、socketA
ワイルドカードアドレスにバインドされてsocketB
いるSO_REUSEADDR
有効として非ワイルドカードアドレスと同じポートにバインドされているsocketA
。このバインドが正常にいない限り、成功します、socketA
していたSO_EXCLBIND
ことが関係なく、失敗した場合には、有効なSO_REUSEADDR
の旗をsocketB
。
その他のシステム
システムが上記にリストされていない場合に備えて、システムがこれら2つのオプションをどのように処理するかを調べるために使用できる小さなテストプログラムを作成しました。また、私の結果が間違っていると思われる場合は、コメントを投稿したり、誤った主張をしたりする前に、まずそのプログラムを実行してください。
コードをビルドするために必要なすべてのビット(ネットワーク部品用)POSIX APIとC99コンパイラである(実際には、ほとんどの非C99コンパイラは限り彼らが提供と同様に動作しますinttypes.h
とstdbool.h
、例えば、gcc
長いフルC99のサポートを提供する前に、両方をサポート) 。
プログラムが実行する必要があるのは、システム内の少なくとも1つのインターフェース(ローカルインターフェース以外)にIPアドレスが割り当てられており、そのインターフェースを使用するデフォルトルートが設定されていることだけです。プログラムはそのIPアドレスを収集し、2番目の「特定のアドレス」として使用します。
考えられるすべての組み合わせをテストします。
- TCPおよびUDPプロトコル
- 通常のソケット、リッスン(サーバー)ソケット、マルチキャストソケット
SO_REUSEADDR
socket1、socket2、または両方のソケットに設定
SO_REUSEPORT
socket1、socket2、または両方のソケットに設定
0.0.0.0
(ワイルドカード)、127.0.0.1
(特定のアドレス)、およびプライマリインターフェイスで見つかった2番目の特定のアドレス(マルチキャストの場合224.1.2.3
は、すべてのテストに含まれる)から作成できるすべてのアドレスの組み合わせ
結果を素敵な表に出力します。またSO_REUSEPORT
、知らないシステムでも機能します。この場合、このオプションはテストされません。
プログラムが簡単にテストできないのは、ソケットをその状態に強制して維持するのが非常に難しいためSO_REUSEADDR
、TIME_WAIT
状態のソケットにどのように作用するかです。幸い、ほとんどのオペレーティングシステムは、ここではBSDのように動作するように見え、ほとんどの場合、プログラマーはその状態の存在を単に無視できます。
ここにコードがあります(ここに含めることはできません。回答にはサイズ制限があり、コードはこの応答を制限を超えてプッシュします)。
INADDR_ANY
、既存のローカルアドレスはバインドされませんが、将来のすべてのアドレスがバインドされます。listen
確かに不可能だと言っていても、プロトコル、ローカルアドレス、ローカルポートがまったく同じソケットが作成されます。