Re: connect(2) for UDP
"James K. Lowden" <[email protected]>
| Newsgroups | gmane.comp.db.tds.freetds |
|---|---|
| Message-ID | <[email protected]> |
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