Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I think you might be referring to the <code>SO_REUSEPORT</code> option available on some systems.</p> <p>From the BSD man page:</p> <blockquote> <p>SO_REUSEPORT allows completely duplicate bindings by multiple processes if they all set SO_REUSEPORT before binding the port. This option permits multiple instances of a program to each receive UDP/IP multicast or broadcast datagrams destined for the bound port.</p> </blockquote> <p>Implementations vary a lot for this (from non-existant, to restricted to UDP, to allowing TCP also). In the cases where TCP is allowed, the connexions are distinguished by <em>both</em> source and target (ip,port) pairs. This is sufficient to allow the implementation to decide which app needs which packet. (see <a href="http://wiki.treck.com/Socket_Options" rel="nofollow noreferrer">Trek - Socket options</a> for instance.)</p> <p>With multiple apps bind to the same TCP port, you could only have one socket <code>accept</code>ing on the port. The others would use the port to initiate outbound connections. The TCP stack always knows where to send the packets to.</p> <ul> <li>incoming packets that initiate (SYN) a connection go to the only accepting socket</li> <li>incoming packets for a connected stream are routed to the socket they belong to</li> </ul> <p>Note: the sockets themselves (including, I believe the accepting socket) can be shared across multiple processes. See <a href="https://stackoverflow.com/questions/670891/is-there-a-way-for-multiple-processes-to-share-a-listening-socket">Is there a way for multiple processes to share a listening socket?</a> for example.</p> <hr> <p>Here's how it could work. Voluntarily simplifying TCP (no three-way handshake). Let's note the socket information held by the TCP stack like this</p> <pre><code>(socketname)[owner app, (local IP, local port), (state, remote IP, remote port)] </code></pre> <p>With that, let's set up three apps A, B and C:</p> <pre><code>App A -&gt; bind (localhost,12345,SO_REUSEPORT) TCP stack: create socket (s1)[belongs to A, (localhost,12345), (not connected)] App A &lt;- s1 App B -&gt; bind (localhost,12345,SO_REUSEPORT) TCP stack: create socket (s2)[belongs to B, (localhost,12345), (not connected)] App B &lt;- s2 App C -&gt; bind (localhost,12345,SO_REUSEPORT) TCP stack: create socket (s3)[belongs to C, (localhost,12345), (not connected)] App C &lt;- s3 App C -&gt; s3.listen() TCP stack: update socket (s3)[belongs to C, (localhost,12345), (open for business)] App C -&gt; s3.accept() </code></pre> <p>At this point, no data has been sent, but the kernel knows exactly what socket belongs to what application. Let's have A actually try to do something with its socket:</p> <pre><code>App A -&gt; s1.connect(otherhost,54321) TCP stack: update socket (s1)[belongs to A, (localhost,12345), (connecting, otherhost,54321)] TCP stack: send SYN </code></pre> <p>Here, three things can happen:</p> <p><li> incoming ACK packet from (otherhost,54321) with correct sequence: this is fine, it's for s1, no other possibility</p> <pre><code> TCP stack: update socket (s1)[belongs to A, (localhost,12345), (connected,otherhost,54321)] TCP stack: send SYN/ACK TCP stack: notify App A that socket is connected App A &lt;- connect succeeded, you can start doin' stuff </code></pre> <p><li> incoming SYN packet from (client,4343): can only be for s3, only socket ready for SYN</p> <pre><code> TCP stack: create new socket (s4)[belongs to C, (localhost,12345), (connected,client,4343)] TCP stack: send ACK to client TCP stack: notify App C that (s4) has been accepted App C &lt;- s4 returned from accept() </code></pre> <p><li> incoming packet from somewhere else:</p> <pre><code> TCP stack: drop or reject, there are no matching sessions </code></pre> <p>Let's imagine the two things above happened. The kernel information is now:</p> <pre><code>(s1)[belongs to A, (localhost,12345), (connected,otherhost,54321)] (s2)[belongs to B, (localhost,12345), (not connected)] (s3)[belongs to C, (localhost,12345), (open for business)] (s4)[belongs to C, (localhost,12345), (connected,client,4343)] </code></pre> <p>Now four kinds of packets can come in:</p> <p><li> incoming normal packet from (otherhost,54321): this matches s1, hand it over to App A <li> incoming normal packet from (client,4343): this matches s4, hand it over to App C <li> incoming SYN packet from (otherclient,2398): this matches s3, same as before <li> anything else: drop or reject, invalid state</p> <p>The TCP stack always nows which socket a packet belongs to. So it knows where to deliver the data.</p> <hr> <p><code>SO_REUSEADDR</code> is different: it only allows to bind to a port in <code>TIME_WAIT</code> state - i.e. the port is already closing down, the socket that had opened it has been issued a <code>close</code> already (more or less, there are other conditions). With <code>SO_REUSEADDR</code>, only one socket at a time holds the socket open.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload