Skip to Content.
Sympa Menu

freetds - Re: [freetds] connect(2) for UDP

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: "James K. Lowden" <jklowden AT freetds.org>
  • To: FreeTDS Development Group <freetds AT lists.ibiblio.org>
  • Subject: Re: [freetds] connect(2) for UDP
  • Date: Mon, 15 Dec 2008 21:12:57 -0500

Jackson, Craig (Gale) wrote:
> I don't think connect(2) sends any packets
> for UDP. It just sets up bookkeeping for subsequent write() and read()
> calls.

Thanks for pointing that out. You're right, it's not until the connected
socket is read from that the caller learns there's no one listening. But
the read(2) call fails immediately, which sure is quicker than the
shout-and-pray arrangement we're using now. ;-)

You know, could I just say something about this? Considering that the
Internet is built on TCP/IP, a 25 year-old technology, this sort of thing
is remarkably hard to verify with only the WWW at one's disposal. I
thought I'd be able to send you a link to a definitive example, and I
don't find one -- or even much good advice -- online.

I got the idea from Chapter 8.11 of Stevens's "Unix Network Programming",
Volume 1, 3rd edition, page 252.  And he says what you said:

"[T]he kernel just checks for any immediate errors ... records the IP
address and port number of the peer ... and returns immediately to the
calling process."

He also notes:

"Overloading the connect() function with this capability for UDP
sockets
is confusing. If the convention that 'sockname' is the local protocol
address and 'peername' is the foreign protocol address is used, then a
better name would have been setpeername()."

> However, I think after a write(), a subsequent read() may be able to
> learn that it had gotten an ICMP Port Unreachable, which is the
> diagnostic when no one is listening on a UDP port.

Quite so. Here's the output from my test program to an unserviced port on
a running host:

$ time ./connect_udp -h cherry -p4
address of cherry is 192.168.1.254
connecting UDP socket to cherry:4 ... done
writing to cherry:4 ... done. (wrote 2)
reading from cherry:4 ... socket ready ... error: Connection refused

real 0m0.011s
user 0m0.000s
sys 0m0.000s

connect(2) and write(2) both succeed, as does select(2), indicating the
socket is ready. Which it is, with ECONNREFUSED. In 11 milliseconds!

The same program, when trying to communicate with a down host, times out
reading. Not surprising, on reflection, because there's no machine to
send that ICMP message.

This is actually highly useful! Yes, we can know if instance-name support
is running on a given host, which is a nice improvement. But I've been
looking into getting better connection messages into tsql: distinguishing
between resolver, host down, and server-not-listening, TDSVER, and
authentication errors. To write ICMP packets I need raw sockets, which is
hard and requires superuser privileges on most OSes. Using a connected
UDP socket, I can distinguish between no host and no port with no special
privileges.

Regards,

--jkl




Archive powered by MHonArc 2.6.24.

Top of Page