5

I recently posted here asking about the drawbacks of having a server process bind to a dynamically assigned port. That approach came about because xinetd, which launched the server process, allocates STDIN and STDOUT as the server's communication channel to the client, and we wanted the server to use a bidirectional socket. The responses (and our operations team) convinced me to abandon that approach.

I need a daemon process to monitor a designated port and fork concurrent servers. The server process is written using an I/O infrastructure that is socket-based. We have developed a server process that can be launched by xinetd. The first thing it does is to bind to a dynamically-assigned port number, send the port number to the client over STDOUT, and then listen on the socket for the client's connect() - at which point it is good to go with the socket-based I/O infrastructure.

Our operations team has nixed the use of dynamic ports on security grounds (see link). I'm looking for an alternate way for a client to connect to a dynamically-spawned server and communicate using sockets. The simplest solution would be something identical in most respects to xinetd, but which, instead of allocating STDIN/STDOUT as the server's connection to the client, would pass the socket that was allocated when the daemon accept()ed the connection, to the server. Presumably, since the socket number wouldn't be predictable, the daemon would also need to pass the number as a command line arg.

I have written such a daemon in Perl, but I hesitate to roll my own because I'm certain that (x)inetd is far better "hardened" than what I could easily come up with.

So that's the problem, and what I conceive to be the simplest solution. I'd appreciate hearing alternate solutions, or even whether in fact xinetd can be configured to pass a socket as I described.

  • 1
    "CTO wants me to research whether there is some industry-hardened open source solution" -- Questions asking us to recommend a tool, library or favorite off-site resource are off-topic for Programmers as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it. – gnat Aug 6 '13 at 19:00
  • 1
    Well, @gnat, check it out. Any better? – Chap Aug 6 '13 at 19:31
  • that looks much better (you're apparently pretty good at editing) – gnat Aug 6 '13 at 19:34
  • I see close "tool-recommendation" votes piling on your question, probably by inertia. If you notice it gets closed, please feel free to ping me, I'll do my best to reopen – gnat Aug 6 '13 at 22:23
  • @gnat: Thanks. I'm unclear what's meant by "tool" in this case -- for example, is xinetd considered a tool? Is there perhaps a better forum for this question; e.g. SO or Unix/Linux? – Chap Aug 6 '13 at 22:53
3

You're trying to make things too complicated. If you want to use xinetd, write your application to run each new instance talking over stdin/stdout. If you want to directly use sockets, have your service listen on a fixed socket and handle the connections itself.

You don't have any compelling arguments for why you need to complicate things like this, you just seem to think it's the only solution. Either you're leaving out major details, you're confused about how networking works or we're dealing with an X Y Problem.

You say you want to use a "bidirectional socket" - when you have stdin/stdout that'a bidirectional channel. Unless you plan on using complex ioctls, there's not really any difference - "passing a socket" isn't buying you anything.

You say that xinetd is "hardened" - if you're on a private, firewalled network, it's safe to write your own daemon to listen directly on a fixed port. If you're concerned about security or DOSes, xinetd doesn't buy you much.

What is wrong with either of the simple approaches?

  • I cant really answer all your questions here. The socket-using infrastructure was already written; the service(s) would have to be launched at startup if they were to handle connections directly. As it turned out, I wrote what I needed in Perl (which itself has to be launched at startup). The passing of the opened socket descriptor, something unnecessary with xinetd's STDIO, was something I did with a command line argument provided by the launch daemon. (BTW, "compelling arguments" are sometimes "because the CTO and Operations say so") – Chap Sep 11 '13 at 23:18
1

The first question is simply 'why can you not use the stream IO from xinetd? Other than you saying you want to use socket IO, there is no clear explanation of why you need to make life more complicated for your self.

If you really do need to handle sockets yourself, the solution is to implement your own socket server. From a process perspective, its really straightforward. You create your server socket, listen for connection, and then when you accept each connection you have a client specific socket for you to provide your service.

However, here is where things get a lot more interesting. you will need to support multiple client connections without one request blocking other requests. The simplest strategy is based on how xinetd solves this, by forking a new process and the new process handles that client connection and exits when the socket closes. If you are planing a service that is not going to be heavily loaded, this is good enough for you.

To handle 1k+ connections at a time, using fork() and creating a new process becomes very inefficient. Lots of memory, lots of context switching, and performance starts to fade. This is where you need to switch to an asynchronous IO approach.

  • See above. I duplicated xinetd functionality - spawn multiple concurrent instances. Load will be 10-20 connections at most. – Chap Sep 11 '13 at 23:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.