views:

127

answers:

5

Hi, is there a way to bind multiple listening TCP sockets on the same {IP, port}? I know I can just open a socket, bind, fork and then listen in each of the processes. But I'd like to do the same with separate processes that cannot fork after binding. Is there some way to allow this and not get the "Address already in use" error?

The only option I need is automatic load-balancing of the connections.

+2  A: 

Unfortunately, i don't believe this is possible.

srparish
+3  A: 

You could do something similar and pass the socket fd through a unix domain socket as suggested here

Hasturkun
Yep - a file descriptor passed through a UNIX domain socket is just like one duplicated through `fork()`.
caf
+4  A: 

It looks like it makes sense to introduce a separate process that would listen on the port and act as a load balancing proxy forwarding the traffic to a pool of backend processes, either over the loopback interface or Unix sockets. If you're dealing with HTTP you could use one of the existing HTTP reverse proxies, like pound or nginx.

Adam Byrtek
+1  A: 

Only one process can bind TCP socket to a given port and IP address (even if it's INADDR_ANY) - that would be a completely duplicate binding. The only exception to this is the bind(2)/fork(2) dance, as you already mentioned.

That said, if you have multiple network interfaces on the machine (or setup IP aliases on a single interface), you can bind one socket to each IP address with the same port. Just remember to set SO_REUSEADDR socket option between socket(2) and bind(2) calls.

Load balancing could be done in multiple ways:

  • do it on a firewall mapping source IPs to pool of machines/ports,
  • proxy/pre-process in one process, do real work in a pool of processes,
  • use file descriptor passing as @Hasturkun suggests.
Nikolai N Fetissov
As the OP says, you can arrange for this state of affairs (multiple processes listening on the same local port and address pair) with `fork()`. The kernel resolves the issue by delivering each new connection to an arbitrarily-chosen listening process.
caf
Yep, new connection is an event, not part of a stream. Will re-phrase. thanks.
Nikolai N Fetissov
A: 

For a highly expert variation of your task, on Linux you may map incoming packets into your process, via using netfilter's queue module. Then you can drop/modify/them.

prog1: checks if packet came from IP xxx.xxx.xxx. Match? Catch packet.
prog2: checks if prog3 busy. Match? Catch packet.
prog3: checks packet's origin...

However this results in ~20Kb of code just to handle packets, and your TCP/IP stack wont survive it long (big traffic == big mistake).

On Windows, you can achieve same with Winsock driver.

It's an esotheric solution, just create one dispatcher process to fork your others. Look after nginx, or apache2, or cometd, or any Perl's asynchronous TCP module to catch the idea.

mhambra