/etc/services on your system. It is also a good idea to let users customize the port number in case of conflicts with other un- registered port numbers in other servers. The best way of doing this is hardcoding a service name, and using getservbyname() to lookup the actual port number. This method allows users to change the port your server binds to by simply editing the /etc/services file.
SO_REUSEADDR allows your server to bind to an address which is in a TIME_WAIT state. It does not allow more than one server to bind to the same address. It was mentioned that use of this flag can create a security risk because another server can bind to a the same port, by binding to a specific address as opposed to INADDR_ANY. The SO_REUSEPORT flag allows multiple processes to bind to the same address provided all of them use the SO_REUSEPORT option.
From Richard Stevens ( stevens@noao.edu):
This is a newer flag that appeared in the 4.4BSD multicasting code (although that code was from elsewhere, so I am not sure just who invented the new SO_REUSEPORT flag).
What this flag lets you do is rebind a port that is already in use, but only if all users of the port specify the flag. I believe the intent is for multicasting apps, since if you're running the same app on a host, all need to bind the same port. But the flag may have other uses. For example the following is from a post in February:
From Stu Friedberg ( tuartf@sequent.com):
SO_REUSEPORT is also useful for eliminating the try-10-times-to-bind hack in ftpd's data connection setup routine. Without SO_REUSEPORT, only one ftpd thread can bind to TCP (lhost, lport, INADDR_ANY, 0) in preparation for connecting back to the client. Under conditions of heavy load, there are more threads colliding here than the try-10-times hack can accomodate. With SO_REUSEPORT, things work nicely and the hack becomes unnecessary.
I have also heard that DEC OSF supports the flag. Also note that under 4.4BSD, if you are binding a multicast address, then SO_REUSEADDR is condisered the same as SO_REUSEPORT (p. 731 of "TCP/IP Illustrated, Volume 2"). I think under Solaris you just replace SO_REUSEPORT with SO_REUSEADDR.
From a later Stevens posting, with minor editing:
Basically SO_REUSEPORT is a BSD'ism that arose when multicasting was added, even thought it was not used in the original Steve Deering code. I believe some BSD-derived systems may also include it (OSF, now Digital Unix, perhaps?). SO_REUSEPORT lets you bind the same address *and* port, but only if all the binders have specified it. But when binding a multicast address (its main use), SO_REUSEADDR is considered identical to SO_REUSEPORT (p. 731, "TCP/IP Illustrated, Volume 2"). So for portability of multicasting applications I always use SO_REUSEADDR.
The original question was actually from Shankar Ramamoorthy ( hankar@viman.com):
I want to run a server on a multi-homed host. The host is part of two networks and has two ethernet cards. I want to run a server on this machine, binding to a pre-determined port number. I want clients on either subnet to be able to send broadcast packates to the port and have the server receive them.
And answered by Andrew Gierth ( ndrew@erlenstar.demon.co.uk):
Your first question in this scenario is, do you need to know which subnet the packet came from? I'm not at all sure that this can be reliably determined in all cases.
If you don't really care, then all you need is one socket bound to INADDR_ANY. That simplifies things greatly.
If you do care, then you have to bind multiple sockets. You are obviously attempting to do this in your code as posted, so I'll assume you do.
I was hoping that something like the following would work. Will it? This is on Sparcs running Solaris 2.4/2.5.
I don't have access to Solaris, but I'll comment based on my experience with other Unixes.
[Shankar's original code omitted]
What you are doing is attempting to bind all the current hosts unicast addresses as listed in hosts/NIS/DNS. This may or may not reflect reality, but much more importantly, neglects the broadcast addresses. It seems to be the case in the majority of implementations that a socket bound to a unicast address will not see incoming packets with broadcast addresses as their destinations.
The approach I've taken is to use SIOCGIFCONF to retrieve the list of active network interfaces, and SIOCGIFFLAGS and SIOCGIFBRDADDR to identify broadcastable interfaces and get the broadcast addresses. Then I bind to each unicast address, each broadcast address, and to INADDR_ANY as well. That last is necessary to catch packets that are on the wire with INADDR_BROADCAST in the destination. (SO_REUSEADDR is necessary to bind INADDR_ANY as well as the specific addresses.)
This gives me very nearly what I want. The wrinkles are:
This question is usually asked by people who are testing their server with telnet, and want it to process their keystrokes one character at a time. The correct technique is to use a psuedo terminal (pty). More on that in a minute.
According to Roger Espel Llima ( spel@drakkar.ens.fr), you can have your server send a sequence of control characters: 0xff 0xfb 0x01 0xff 0xfb 0x03 0xff 0xfd 0x0f3, which translates to IAC WILL ECHO IAC WILL SUPPRESS-GO-AHEAD IAC DO SUPPRESS-GO-AHEAD. For more information on what this means, check out std8, std28 and std29. Roger also gave the following tips:
socket's IO to it, but I'm not getting all the data across. Why?
If the program you are running uses printf(), etc (streams from stdio.h) you have to deal with two buffers. The kernel buffers all socket IO, and this is explained in ``section 2.11''. The second buffer is the one that is causing you grief. This is the stdio buffer, and the problem was well explained by Andrew:
(The short answer to this question is that you want to use a pty rather than a socket; the remainder of this article is an attempt to explain why.)
Firstly, the socket buffer controlled by setsockopt() has absolutly nothing to do with stdio buffering. Setting it to 1 is guaranteed to be the Wrong Thing(tm). Perhaps the following diagram might make things a little clearer:
Process A Process B +---------------------+ +---------------------+ | | | | | mainline code | | mainline code | | | | | ^ | | v | | | | | fputc() | | fgetc() | | | | | ^ | | v | | | | | +-----------+ | | +-----------+ | | | stdio | | | | stdio | | | | buffer | | | | buffer | | | +-----------+ | | +-----------+ | | | | | ^ | | | | | | | | write() | | read() | | | | | | | +-------- | ----------+ +-------- | ----------+ | | User space ------------|-------------------------- | --------------------------- | | Kernel space v | +-----------+ +-----------+ | socket | | socket | | buffer | | buffer | +-----------+ +-----------+ | ^ v | (AF- and protocol- (AF- and protocol- dependent code) dependent code)
If it's an option, you can use some standalone program that will just run something inside a pty and buffer its input/output. I've seen a package by the name pty.tar.gz that did that; you could search around for it with archie or AltaVista. Another option (**warning, evil hack**) , if you're on a system that supports this (SunOS, Solaris, Linux ELF do; I don't know about others) is to, on your main program, putenv() the name of a shared executable (*.so) in LD_PRELOAD, and then in that .so redefine some commonly used libc function that the program you're exec'ing is known to use early. There you can 'get control' on the running program, and the first time you get it, do a setbuf(stdout, NULL) on the program's behalf, and then call the original libc function with a dlopen() + dlsym(). And you keep the dlsym() value on a static var, so you can just call that the following times.
(Editors note: I still haven't done an expample for how to do pty's, but I hope I will be able to do one after I finish the non-blocking example code.)