From: torek@torek.net (Chris Torek)
Subject: [TUHS] Sockets and the true UNIX
Date: Thu, 21 Sep 2017 13:36:38 -0700 [thread overview]
Message-ID: <201709212036.v8LKac1u063236@elf.torek.net> (raw)
In-Reply-To: Your message of "Thu, 21 Sep 2017 09:17:44 -0700." <20170921161744.GD25650@mcvoy.com>
>... I've never been fond of the socket API though I
>am sympathetic, it's easy to do the easy parts as /dev/tcp but as I
>recall there are all sorts of weird cases that don't fit.
There's no reason it could not be done literally with entries
similar to /dev ones, since each socket() takes some arguments
(domain, type, protocol) which could be represented as directly
as:
/socket/domain/type/protocol_or_default
for instance. For the typical s = socket(PF_INET, SOCK_STREAM, 0)
you would open "/socket/inet/stream/tcp". To distinguish
between UDP and RDP you'd open "/socket/inet/dgram/udp" vs
"/socket/inet/dgram/rdp". Of course these days there's a
<type> constant for reliable datagram, and some of these are
just overcomplicating things: /socket/inet/tcp, /socket/inet/icmp,
etc., would actually suffice, but there's an obvious one
to one mapping from "socket" arguments to strings under
"/socket" or whatever top level name you want.
More fundamentally, a socket itself is only "half initialized".
It's neither bound to any local address, nor connected to any
remote address. The BSD kernel interface introduced two
system calls, bind() and connect(), to let you specify these
two halves. But these two calls are wrong! It needs to be
*one* call, that does both operations simultaneously, so as to
allow you to specify that you want the system to provide the
local or remote address. You supply one or both. To supply
only one, pass in a NULL for the other one.
* You supply only the remote address: "I want to connect to
someone and I know their address, so just pick a local one
that works." This is currently written as connect().
* You supply only the local address: "I want to be a server."
This is currently written as bind() followed by listen()
followed by a series of accept()s. There's no reason for
a separate listen() call (it takes a "backlog" argument but
in practice everyone defaults it and the kernel does strange
manipulations on it.) This also knocks out the need for
SO_REUSEADDR, because the kernel can tell at the time of
the call that you are asking to be a server. Either someone
else already is (error) or you win (success).
* You supply both halves at the same time. (This is the
special case FTP requires.) "I want to connect to someone
and I know he expects me to be address <L>.")
This is a rare special case. We need a way to reserve an
address. But it's rare, let's make *it* the complicated one.
If you supply both halves at the same time, you can pass
pointers to two all-zero addresses, both local and remote.
This is different from passing in a NULL ("I don't care"): it
means "I do care, get me an address" (reserving it) along with
"I can't actually connect yet".
Now you have the "3/4ths done" socket. You know what your
local address will be. You give this to the remote, and
call the system call again with the other guy's IP address
this time.
That's not optimal (sometimes the local address you want to
use depends on the remote address you will use), but it's what
the existing system calls give you anyway, as you can't call
connect() first, you must call bind() first.
Also, the profusion of system calls (send, recv, sendmsg, recvmsg,
recvfrom) is quite unnecessary: at most, one needs the equivalent
of sendmsg/recvmsg.
So we could right away do this:
bind(), listen(), connect() => setconn()
send(), sendmsg() => sendmsg()
recv(), recvfrom(), recvmsg() => recvmsg()
even without figuring out how to properly implement /dev/tcp
or whatever.
Of course, it's a bit late. :-)
Chris
next prev parent reply other threads:[~2017-09-21 20:36 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-21 16:01 Ian Zimmerman
2017-09-21 16:07 ` Chet Ramey
2017-09-21 16:10 ` Larry McVoy
2017-09-21 16:20 ` David Edmondson
2017-09-21 16:25 ` Clem Cole
2017-09-21 16:27 ` Larry McVoy
2017-09-21 16:37 ` [TUHS] Sockets and the true UNIX [ actually carping about streams ] Jon Steinhart
2017-09-21 18:26 ` [TUHS] Sockets and the true UNIX Chet Ramey
2017-09-21 16:13 ` Jon Steinhart
2017-09-21 16:17 ` Larry McVoy
2017-09-21 20:36 ` Chris Torek [this message]
2017-09-21 18:56 ` Bakul Shah
2017-09-21 19:13 ` Steve Simon
2017-09-21 19:31 ` Bakul Shah
2017-09-21 20:15 ` ron minnich
2017-09-21 20:34 ` Clem Cole
2017-09-21 23:26 ` Dave Horsfall
[not found] <mailman.1105.1506026200.3779.tuhs@minnie.tuhs.org>
2017-09-22 10:36 ` Paul Ruizendaal
2017-09-22 14:32 ` Clem Cole
2017-09-22 14:42 ` Chet Ramey
2017-09-22 14:47 ` Chet Ramey
2017-09-22 14:52 ` Lars Brinkhoff
2017-09-22 14:49 ` Larry McVoy
2017-09-22 14:57 ` Chet Ramey
2017-09-22 18:14 ` Chris Torek
2017-09-22 18:43 ` Clem Cole
2017-09-22 19:08 ` Chet Ramey
2017-09-22 20:57 ` Chris Torek
2017-09-24 18:04 ` Chet Ramey
2017-09-22 18:00 ` Chris Torek
2017-09-25 17:57 Norman Wilson
2017-09-25 18:55 ` Clem Cole
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=201709212036.v8LKac1u063236@elf.torek.net \
--to=torek@torek.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).