Rhandom has asked for the wisdom of the Perl Monks concerning the following question:

Here is a fun one that I would love to see an answer to. I have a server class that can simultaneously bind to a port under UDP and TCP. When I bind to port I keep track of which fileno is open to each protocol. Because of this, when I receive a connection, I can use my internal table of fileno's to look up which protocol was bound on it.

Now the trick. I also have my server able to run from inetd (or xinetd). The problem is here that when a connection comes in, I don't know if I'm looking UDP or TCP (remember, I can bind the same port and same host under different protocols at the same time under the regular server -- inetd can also, but it doesn't tell me which one I received). So, the question is, is there a method that will give you which protocol is being used. I have looked at Socket and I have looked at IO::Socket and I have looked at IO::Socket::INET but with little success. I have even guessed some method names out of the air. Is there anybody with insight into the socket internals who has any idea? Is this even possible?

Any ideas? There is the option of using separate programs for UDP and for TCP. I don't want to do this though (I don't need to under my regular server -- I'd like to maintain the same code base).

The winner will get their name in lights (or at least a mention in the module credits) (but we don't do things for fame around here do we {grin}).

my @a=qw(random brilliant braindead); print $a[rand(@a)];

Replies are listed 'Best First'.
Re: Determinine Protocol In inetd.
by merlyn (Sage) on Apr 28, 2001 at 18:39 UTC
    If I recall, you can specify parameters in the inetd.conf, so just call the program two different ways by passing a parameter.

    -- Randal L. Schwartz, Perl hacker

      This is probably the easiest approach. Another is to try to get the TCP option TCP_MAXSEG and if it fails, it is a UDP socket.

      You can, however, get the info you want if you are using Linux. I don't know about other OSs as I don't have any other development platforms here. If you do a

      getsockopt SOCK, SOL_SOCKET, SO_TYPE;
      it will (should?) return SOCK_STREAM for stream (TCP) sockets and SOCK_DGRAM for datagram (UDP) sockets. This looks like it works from C, but on my perl5.005003 it seems to have a problem. Maybe it's my system...

      HTH, traveler

        After investigating it, you are correct. That would be the best way to get it. However, it is disabled in most of the perl versions I have looked at. Thanks for the work. I'll have to continue recording information the way that I was.
        perl -we 'use Socket; Socket::getsockopt()' Your vendor has not defined Socket macro getsockopt, used at -e line 1
        my @a=qw(random brilliant braindead); print $a[rand(@a)];
      I mentioned this as a possibility. If I have to I will. But I would rather that the code could determine it on its own.

      Even without passing parameters I could write a dummy script:
      #!/usr/bin/perl exec "MyRealProg.pl --proto=udp"
      Course, this would be a double exec.

      Is there any way to do it (suppose I wasn't in inetd and I was passed some fileno's of sockets to connect to -- is there a way to determine?)

      my @a=qw(random brilliant braindead); print $a[rand(@a)];
        Looks like getsockopt can be used with an SO_TYPE subcommand to get the type such as SOCK_STREAM. I don't have working code, but something along that line should be useful.

        -- Randal L. Schwartz, Perl hacker

        But I would rather that the code could determine it on its own.

        identd has the protocol in hand, yet you prefer to drop this knowledge on the floor and then rederive it downstream. Curiousity about how you might be able to derive the discarded prototype info is one thing, but from a pragmatic point of view, this is wasteful a approach.