[comp.protocols.tcp-ip] sockets vs. streams

mrc@Tomobiki-Cho.CAC.Washington.EDU (Mark Crispin) (09/01/90)

If "network I/O looks like local device I/O" under Unix then when the
h*ll do I have to worry about all the socket or streams crap?

If I want to connect to port 0.143 on host 128.95.112.69, why can't I
do something like
  open ("/tcp/128.95.112.69-0.143",O_RDWR|O_CREAT,0);
(O_RDWR for bidirectional and O_CREAT to mean an active connection
instead of a listening connection)???

Or better yet, fopen() and all the other stdio calls.

/dev/tcp instead of /tcp would have been OK too if you insist.  I
don't care about the internal operating system semantics, as long as a
filesystem interface is presented.

There seems to be a religion that for some reason it is evil for TCP
to use filesystem I/O calls, although the proponents of this religion
have never given me a good reason why.

 _____   | ____ ___|___   /__ Mark ("Gaijin") Crispin  "Gaijin! Gaijin!"
 _|_|_  -|- ||   __|__   /  / R90/6 pilot, DoD #0105   "Gaijin ha doko?"
|_|_|_|  |\-++-  |===|  /  /  Atheist & Proud          "Niichan ha gaijin."
 --|--  /| ||||  |___|    /\  (206) 842-2385/543-5762  "Chigau.  Gaijin ja nai.
  /|\    | |/\| _______  /  \ MRC@CAC.Washington.EDU    Omae ha gaijin darou"
 / | \   | |__|  /   \  /    \"Iie, boku ha nihonjin." "Souka. Yappari gaijin!"
Hee, dakedo UNIX nanka wo tsukatte, umaku ikanaku temo shiranai yo.

dls@mentor.cc.purdue.edu (David L Stevens) (09/01/90)

	I don't want to get into a religious war, but I don't see where a
filesystem analogy to sockets holds up to any but the most shallow
interpretation. To use your naming, what does it mean if I type:

	cd /tcp//128.210.10.8
?
	What if I do an "ls /tcp"? Be careful-- all of the assigned addresses
aren't available in any one place. Not if NIC.DDN.MIL-- they only have the
network parts...
	How do you specify a local address binding when you care? How do you
specify that you don't care? What does a "seek" mean on a socket? How do you
send urgent data in TCP?
	In a UNIX implementation, by making the "tcp" a directory, you've
introduced a type of pseudo-device like no other that exists and without
it you lose some of the information you want in the name.

	I won't argue that sockets are the "right" way, and there are certainly
rough edges, but the filesystem analagy *is* artificial. The things you do to
files (ie, storage devices) aren't the things you do with sockets (ie,
communication media). To a degree, you can make the same argument with
terminals, but it doesn't seem to be pushing it quite as much there, to me.

	In Dr Doug Comer's operating system, Xinu, he uses an "open" that
specifies remote address/port names in the "filename" as "XXX.XXX.XXX.XXX:port"
and what would be the mode is instead the local port number, if nonzero. It
works ok, but the name space isn't even pretending to be part of the
filesystem. I don't think I've seen any mapping that makes a lot of sense to
me, though I used to be a NewCastle fan... :-)
	It doesn't surpise me that the socket interface is different, then.
I don't know if that qualifies as the explanation you wanted or not, and
perhaps there are better arguments to be made on both sides...

-- 
					+-DLS  (dls@mentor.cc.purdue.edu)

milton@ecn.purdue.edu (Milton D Miller) (09/01/90)

The thing that came to my mind when I first saw this thread was the
multiplexed character driver in AIX.  This is basically a special file,
but allows additional path name component(s) can be added, which get
passed to the driver.  (For those who don't know, AIX is IBM's name for
UNIX.)  With that in mind, let me respond:

In article <13526@mentor.cc.purdue.edu> dls@mentor.cc.purdue.edu (David L Stevens) writes:
>
>	I don't want to get into a religious war, but I don't see where a
>filesystem analogy to sockets holds up to any but the most shallow
>interpretation. To use your naming, what does it mean if I type:
>
>	cd /tcp//128.210.10.8
>?

You get 'Not A Directory', just like any other multiplexed character device.

>	What if I do an "ls /tcp"? Be careful-- all of the assigned addresses
>aren't available in any one place. Not if NIC.DDN.MIL-- they only have the
>network parts...

Same as above, you see a character special multiplexed file.
Someone will probably say you should get a list of all currently known
(ie in use) sockets, but there is no such model in the current AIX
(you could use a special IOCTL for that, I suppose).

>	How do you specify a local address binding when you care? How do you
>specify that you don't care? What does a "seek" mean on a socket? How do you
>send urgent data in TCP?

Open /tcp/whatever and use ioctl().  Seek is same as a tty, ie ignored.

>	In a UNIX implementation, by making the "tcp" a directory, you've
>introduced a type of pseudo-device like no other that exists and without
>it you lose some of the information you want in the name.
>
AIX already has these, and are used for '/dev/hft', the 'High Function 
Terminal', which is the graphics head and can have 16 different sessions.
In AIX 3.1, this is also used for /dev/pty, which creates a new pty if
you don't specify the additional argument.

>	I won't argue that sockets are the "right" way, and there are certainly
>rough edges, but the filesystem analagy *is* artificial. The things you do to
>files (ie, storage devices) aren't the things you do with sockets (ie,
>communication media). To a degree, you can make the same argument with
>terminals, but it doesn't seem to be pushing it quite as much there, to me.
>

[note about Xinu deleted]

>	It doesn't surpise me that the socket interface is different, then.
>I don't know if that qualifies as the explanation you wanted or not, and
>perhaps there are better arguments to be made on both sides...
>
>-- 
>					+-DLS  (dls@mentor.cc.purdue.edu)


As far as names, maybe /dev/net/tcp, that way you could also get
ip, udp, etc. in the same directory.  Or just leave everything in 
/dev.  Also, you would probably want some trailing path to be
an unbound socket, or would just tcp (with out an additional
component) be ok?

milton

Milton D. Miller II
ECN Consultant
Disclaimer: I was a coop student at IBM.

mrc@Tomobiki-Cho.CAC.Washington.EDU (Mark Crispin) (09/01/90)

I'm not convinced how much of this belongs in comp.protocols.tcp-ip
as opposed to a Unix discussion list.  This whole discussion must seem
absurd to someone using something other than Unix.

In article <13526@mentor.cc.purdue.edu> dls@mentor.cc.purdue.edu (David L Stevens) writes:
>	I don't want to get into a religious war, but I don't see where a
>filesystem analogy to sockets holds up to any but the most shallow
>interpretation.

Strange how many "shallow" non-Unix operating systems which accessed
TCP through the filesystem exist.  Are you familiar with any of them?
They did it quite cleanly.

>To use your naming, what does it mean if I type:
>	cd /tcp//128.210.10.8
>?

Nothing in particular.  It can be a no-op or some sort of invalid I/O
operation.

>	What if I do an "ls /tcp"?

You get whatever you get when you open the file "/tcp" for read and
attempt to interpret it as a disk directory.  Remember, ls is just a
user program.  If you were really clever, perhaps the file "/tcp"
could contain a netstat-type report.

>Be careful-- all of the assigned addresses
>aren't available in any one place. Not if NIC.DDN.MIL-- they only have the
>network parts...

Irrelevant.  At most, the directory /tcp would have the currently open
connections as its members.

>	How do you specify a local address binding when you care? How do you
>specify that you don't care?

Encode it in the filename as well, e.g. /tcp/FH-FP-LH-LP format where
any field can be blank and trailing hyphens can be omitted.

>What does a "seek" mean on a socket?

Either a no-op or some sort of invalid I/O error.

>How do you send urgent data in TCP?

Most user programs don't do so often, so an ioctl() of some sort is
alright.

>	In a UNIX implementation, by making the "tcp" a directory, you've
>introduced a type of pseudo-device like no other that exists and without
>it you lose some of the information you want in the name.

What you're really saying is that those of your religion don't want to
support unit-record file I/O and will if necessary rewrite history to
"prove" the argument that it's "meaningless".

>	I won't argue that sockets are the "right" way, and there are certainly
>rough edges, but the filesystem analagy *is* artificial.

Well, then, let's get rid of the /dev kludge and have a special
mechanism for every different device.  We've already started on that
golden path by having sockets and streams to do the same thing.  Let's
see, we can rewind tapes but not printers, I guess we need a different
mechanism for each of these too...

Which reminds me.  Even if you didn't want to encode the connection
parameters in the filename, you still could have had had /dev/tcp and
then some ioctl to open the connection.  No need for any new system
calls (socket(), connect(), listen(), etc.)

>The things you do to
>files (ie, storage devices) aren't the things you do with sockets (ie,
>communication media).

Strange, I distinctly remember doing the exact same things with
storage devices that I do with communications media.  It was real
neat, since I could use I/O redirection for debugging or multiple-use
software.

"Those who forget the past are condemned to repeat it."

 _____   | ____ ___|___   /__ Mark ("Gaijin") Crispin  "Gaijin! Gaijin!"
 _|_|_  -|- ||   __|__   /  / R90/6 pilot, DoD #0105   "Gaijin ha doko?"
|_|_|_|  |\-++-  |===|  /  /  Atheist & Proud          "Niichan ha gaijin."
 --|--  /| ||||  |___|    /\  (206) 842-2385/543-5762  "Chigau.  Gaijin ja nai.
  /|\    | |/\| _______  /  \ MRC@CAC.Washington.EDU    Omae ha gaijin darou"
 / | \   | |__|  /   \  /    \"Iie, boku ha nihonjin." "Souka. Yappari gaijin!"
Hee, dakedo UNIX nanka wo tsukatte, umaku ikanaku temo shiranai yo.

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (09/01/90)

In <6964@milton.u.washington.edu> mrc@Tomobiki-Cho.CAC.Washington.EDU
(Mark Crispin) writes:

>If "network I/O looks like local device I/O" under Unix then when the
>h*ll do I have to worry about all the socket or streams crap?

I think the confusion in this discussion is between reading and
writing on the one hand and opening the connection on the other
hand.

Once a virtual circuit has been set up, the socket mechanism becomes
transparent to the extent networking will allow.  Setting up the
virtual circuit does require more steps than opening a device or file.
I find this fairly understandable, because the BSD socket interface
gives you LOTS of options, and it was designed to be independent of the
underlying transport mechanism.

>If I want to connect to port 0.143 on host 128.95.112.69, why can't I
>do something like
>  open ("/tcp/128.95.112.69-0.143",O_RDWR|O_CREAT,0);...

Like somebody said, it would be nice if there was a library routine
that would make this easy.  I suppose the open() system call could also
do this, but then there might be too much functionality in a single
system call, because it would have to understand all possible protocols
and possibly accept additional parameters for the different types of
sockets and connections that are possible.

Quick!  Get a copy of Stevens's book on UNIX network programming.  The
socket mystery will be gone for ever.
--
Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com>
UUCP:  oliveb!cirrusl!dhesi

bzs@WORLD.STD.COM (Barry Shein) (09/02/90)

Why does everyone assume this topic is so heated? I think the
discussion is long overdue and we'd all benefit from getting it out in
the open (or is that in in the open()?).

I'm mixed on this issue. TOPS-20 had a file-system-like interface (was
that BBN's TCP?) and, to be frank, I found it quite clumsy (tho
interesting.) The string one passed to the open call started to look
more and more like a long string of IBM/JCL and less and less like a
file name as various options were added.

In MRC's example, the fact that the connection was active or passive
was passed via the flags field (O_CREAT in the example.)

That removes a lot of the utility; I can't specify it on a command
line easily, passing what I want transparently thru a utility that
otherwise doesn't really know it's doing network I/O. That should be a
major goal if we are going to bother at all.

But that leads to things like:

	"/dev/tcp/active/192.74.137.5/143/debug=true/...."

or something like that. I guess one could say "so what, at least you
can do it!" (and, in fact, I don't have a good response to that!)

As to David Stevens questions about file system semantics, what does
"cd /dev/anydev" mean now? Nothing, you get back "Not a directory".
In this mythical TCP you might get back something (e.g. some form of
NFS done this way), or not. I don't see that as a serious problem.

Again, with "ls /tcp" it could be treated like a device, in general
nothing happens (you get back info about just "/tcp".) One could
imagine more being done, but that's an acceptable start.

Seek, urgent data etc, none of that stuff works on every device.

I see you're focusing on the filesystem aspect. It's not that TCP *is*
a filesystem, it's that you can address it with the naming conventions
of the filesystem.

I suppose a counter-argument is why then can't I:

	open("/dev/tty06/9600/cbreak/noecho/xtabs/even/nonl",...)

I dunno, why not?

I'm also not convinced that anything that's happened thus far is
mutually exclusive to a filesystem-like interface. Perhaps it would be
too bad to have two similar interfaces, but that's the worst that
could happen.

In fact, it could be implemented right now. Just write a library with
some of the necessary syscalls written at user-level to recognize
names like this (or if they look like regular files then pass them on
to the kernel) and see how it works. This is kids' stuff, if anyone
wants to know how or doubts it can be done send me mail. You don't
have to touch the kernel to do this (at least not to do a proto.)

On systems with shared libraries it could even be made to work with
existing binaries (tho that can get "exciting", but no big deal if you
have an extra disk to boot off of for experimenting.)

I think there was a project out of Purdue several years ago which did
just this (I forget the name.) I remember playing with some software
from there which did something like this, all user level. Or maybe I
was writing it...hmmm.

My experienced guess is that as one puts it all together all sorts of
problems will arise and it'll tend to get kludgier and kludgier as
more crap is added to that string to make it work.

Maybe I'm wrong, but an experiment is easy enough. I can't see why
someone who was terribly interested wouldn't just demo a prototype and
write a paper for all of us to read (perhaps first verifying that it
hasn't been done a half-dozen times before, possibly reporting where
the disappointments existed.)

        -Barry Shein

Software Tool & Die    | {xylogics,uunet}!world!bzs | bzs@world.std.com
Purveyors to the Trade | Voice: 617-739-0202        | Login: 617-739-WRLD

J.Crowcroft@CS.UCL.AC.UK (Jon Crowcroft) (09/02/90)

this reminds me of a great idea from newcastle:
RESCUE (REduced System Call Unix E by gum, i canna recall what the E
was for), an anlaogy with RISC hardware.

i think they got down to about 4 system calls,
you lose all the process ones from the extreme 8th edition idea of
/proc, so processes are created, run and debug with open/read/write
and destroyed with close

remote execution is simple -you use newcastle conenction, and open
/machinename/proc

of course addresses just arent used - just like you dont use inodes
instead of filenames...so all this overloading of things in the name
is unnecassary. all info is in the first component of the path - i.e.
proc is local processes
machinename/proc is remote processes (open /mil.ddn-nic/proc/telnetd,
is a telnet connection to the nic) and so forth
and the talk facility is just a curses version of write to
/machine/dev/tty?.

multicast getsa a bit tricky, i guess you do open("/mil.*", ...)
to give the 3 minute warning:-)

of course, some good things can be taken too far, cant they?

jon.

kre@cs.mu.OZ.AU (Robert Elz) (09/03/90)

In article <6964@milton.u.washington.edu>,
mrc@Tomobiki-Cho.CAC.Washington.EDU (Mark Crispin) writes:
> 
> If "network I/O looks like local device I/O" under Unix then when the
> h*ll do I have to worry about all the socket or streams crap?

There was a time when building network names into the filesystem
was seen as a sensible thing to do - nice and regular, existing
programs would be able to use them, ...

Unfortunately, while its a nice idea, it really won't work in general,
and if it doesn't work in general, its not worth the effort.

First, its perfectly reasonable for an application to check whether
a file exists before attempting to open it, that way more meaningful
error messages can be given - this is kind of hard to do with a
network connection.

Second, while your example gave numbers (/tcp/128....) that would
be useless in practice - the interface would need to use names. 
Since "open" is a kernel routine (if we're not assuming that we're
talking about completely different issues) that means that either
name->number mapping needs to be done in the kernel, or the kernel
needs to have some mechanism to get some kind of user process to do
the mapping for it.

Now assuming that this can be solved, the application needs to
be able to select parameters for the mapping process - How many
attempts should be made to find the translation?  With what delay
between attempts?  Should default domains be appended?  Which?
Should some user defined nic-name to real name be applied?  From
where?  What should be done with "soft" nameserver errors?  Which
server should we be using?

Next, lets assume that that we are able to get the number, somehow,
and the port number (from its name) as well - next we have to
open the connection.  At first sight that's easy - but how do
we specify the MSS, receive and transmit windows, IP header TTL,
TOS, ...

You suggested that all of this could be built into the filename
as optional segments (by now we're getting pretty far from the
traditional notion of a filename, but never mind).  Certainly,
they could - but doing this makes the user (the provider of
the filename) responsible for specifying all this crud - what
does the user care about MSS's?   So, instead the application has to
massage the file name to append all of the various option settings
that it might need (sure - most applications will take kernel
defaults, but the mechanism has to be there - and all of this
has to be done before the connection is opened).

Now, the easy part is solved, TCP just isn't that complex, but
lets extend generality a little and open an OSI MHS (X.400)
connection as well.   In the connection setup here we need
various addresses, XSAP's (for various X), packet sizes,
window sizes, numerous option selections at various levels,
MTA names, passwords, ...   By the time its all specified your
pathname is going to be totally absurd.

This is why the socket() call provides an anonymous file descriptor
(and the streams model does much the same thing).  Having that
file descriptor all the necessary options can be set before the
network is asked to establish the connection - simple applications
may set none at all and rely on defaults, sophisticated applications
might set many.  But its one mechanism that works well for everyone.

A better question might not be, to regularise things, why isn't
all I/O done by first requesting a socket, then connecting to
the object, ie: open(path, mode) might be modelled (very roughly) as

	s = socket(AF_FS, ...);
	setsockopt(FS_MODE, mode);
	connect(s, path, ...);

(with bind() used for creat(0 of course).

Henry Spenser asked why no-one has ever created a standard library
routine to open a connection.  That's something I have wondered
about myself, it seems like a fairly obvious thing to do.   But then
I've never done it either ... I guess its just that opening a net
connection (explicitly) just isn't something that is done all that
often, and isn't really that hard when you need to do it, so neither
I nor anyone else I'm aware of has bothered to define a good simple
interface useful for most applications (this is a case where universal
applicability wouldn't be needed - the underlying mechanism is still
there when required, just as stdio's fopen() doesn't do everything
that open() is capable of).

kre

david@twg.com (David S. Herron) (09/03/90)

In article <13526@mentor.cc.purdue.edu> dls@mentor.cc.purdue.edu (David L Stevens) writes:
>
>	I don't want to get into a religious war, but I don't see where a
>filesystem analogy to sockets holds up to any but the most shallow
>interpretation. To use your naming, what does it mean if I type:
>
>	cd /tcp//128.210.10.8
>?
>	What if I do an "ls /tcp"? Be careful-- all of the assigned addresses
>aren't available in any one place. Not if NIC.DDN.MIL-- they only have the
>network parts...
>	How do you specify a local address binding when you care? How do you
>specify that you don't care? What does a "seek" mean on a socket? How do you
>send urgent data in TCP?
>	In a UNIX implementation, by making the "tcp" a directory, you've
>introduced a type of pseudo-device like no other that exists and without
>it you lose some of the information you want in the name.
>
>	I won't argue that sockets are the "right" way, and there are certainly
>rough edges, but the filesystem analagy *is* artificial. The things you do to
>files (ie, storage devices) aren't the things you do with sockets (ie,
>communication media). To a degree, you can make the same argument with
>terminals, but it doesn't seem to be pushing it quite as much there, to me.

My understanding is that some of the filesystem researchers are
working towards file systems which one would describe better as
"object hierarchies".  In this type of system the semantics of
objects would vary depending on where you are in the hierarchy.
(Part of this could be implemented right now via the "file system
switch" stuff in newer Unices.)

For the /dev/tcp file system the semantics might be that the next
level contains objects whose names are the IP addresses of hosts
to which we are currently communicating.  Part of the semantics of
this level is that it contains (like a directory) objects whose
names are the port number of the relavent end of the connection.

Objects under /dev/tcp would come and go as connections are created
and destroyed.

There would be a system call (ioctl()?) for getting/setting various
parameters of each end of the connection.

It's not too terribly different than stuff currently available
within the range of systems that are called Unix.  My understanding
of the /proc (of v8-v10 and SysVr4 fame) directory is that it acts
similarly -- that objects within it appear and disappear as processes
come and go.  And that ioctl() can get & set various options on
the process.  And that opening the /proc/nnn `file' (object) lets
you read and write the running process.

It would probably be a "good thing" for the /dev/tcp objects to
have appear under other names than just the IP addresses.  After
all, people wanna use names to connect to places... so "/dev/tcp/s.ms.uky.edu"
would be the same as "/dev/tcp/128.163.128.19", might be implemented as
a link(?).  There would have to be some code here to do nameserver
lookups and set these links up.  An internally multitasking OS might
be a big help here.

Same sort of deal for the next layer down.  /dev/tcp/s.ms.uky.edu/smtp
for instance.

Of course user level applications shouldn't require users to type such
nonsense, but should look pretty much like they do now but make translations.

You could have a routine that returns a free port.  It'd be a simple
use of opendir() and readdir() to find the first free one.

Oh yeah, opendir() and readdir() type stuff might have to be played
with a little bit.  But probably not since they get implemented
in the kernel nowadays.

Just tossing out a few ideas that I've had in my mind for a long time....
Do with them what you will. :-)  I don't think there's anything
unimplementable, and in fact it would likely work pretty darn well.
I would certainly like to see a lot more use made of that file system
switch facility.  Sun OS v4.1 was a good step in that direction in
that it's supporting some pretty funky options/variations to file systems.


-- 
<- David Herron, an MMDF & WIN/MHS guy, <david@twg.com>
<- Formerly: David Herron -- NonResident E-Mail Hack <david@ms.uky.edu>
<-
<- Sign me up for one "I survived Jaka's Story" T-shirt!

zweig@cs.uiuc.edu (Johnny Zweig) (09/04/90)

In my (object-oriented) implementation of TCP, the interface to the TCP
processing module is based on TCP-messages.  You can set/check flags and
numbers and all that kind of crap.  It is somebody else's job to make it look
like a file or whatever.  If you want a file that automagically creates a
network connection when you open it (and what is this /dev/tcp/XXX nonsense
all about? Sheesh! I want a file called "Dad" that opens a connection to the
talk daemon on pop's macintosh when I open it r/w -- this silly business with
IP addresses and port numbers is just as much Someone Else's Problem as making
the whole goddamn mess look like a file).

I think this whole discussion is misguided (though convenient for those of us
who wish to Change the World) in that it makes the assumption that there is
some best way to think about network communications.  This is false.
Networking is complicated (Zweig's Axiom).

The paradigm for thinking about something and the something itself are
different, and if the great minds behind UNIX can't hack that, well, shout at
them (as Mark appears to be doing).  A corrollary to the fact that they are
different is that they should be handled by different pieces of the OS.

-Johnny Paradigm

mrc@Tomobiki-Cho.CAC.Washington.EDU (Mark Crispin) (09/05/90)

In article <5329@munnari.oz.au> kre@cs.mu.OZ.AU (Robert Elz) writes:
>There was a time when building network names into the filesystem
>was seen as a sensible thing to do - nice and regular, existing
>programs would be able to use them, ...

Yes, many dinosaur operating systems did just that.  There are still a
few examples of those dinosaurs, and they are running just fine with
precisely that mindset.  That is not the reason they are dinosaurs;
more likely, the antiquity of the hardware platform is more
responsible for their extinction.

>Unfortunately, while its a nice idea, it really won't work in general,
>and if it doesn't work in general, its not worth the effort.
                                    ^^^^^^^^^^^^^^^^^^^^^^^^
I think this is more the the point than anything else.  The high
priests of sockets don't think it is worth the effort to support
heresy.

>[lots of spurious arguments about why simple things must be made
> harder than necessary]

All of these problems (even DNS lookups of hosts in filenames) were
solved in other operating systems.  It doesn't matter *how*
complicated the most complicated file specifier can be; all that
matters is that the defaults are the right thing for all but the
oddball cases so the simple case is simple.

>Now, the easy part is solved, TCP just isn't that complex, but
>lets extend generality a little and open an OSI MHS (X.400)
>connection as well.

X.400 is at an entirely different level (not to mention stack) from
TCP.  You are mixing apples with orange juice.  The OSI IP stack is
probably a different device from /dev/tcp, and what layers on top of
it is specific to that device.

>Having that
>file descriptor all the necessary options can be set before the
>network is asked to establish the connection

Here's the rub, and the real reason why we've been made to suffer with
streams.  However, this is conceptually easy to solve.  Make the
O_NDELAY form of open with none of {O_RDONLY | O_WRONLY | O_RDWR} set
to mean "give me a designator only", and then have an ioctl() call
that means "establish connection on this designator".  Since we allow
non-blocking open with establish (implicitly above), we probably want
to have all the likely functions: block until open, establish and
block, establish without blocking, test if open.

Summary: the simple cases should be *simple*, not made complex for a
theoretical complex case.

 _____   | ____ ___|___   /__ Mark ("Gaijin") Crispin  "Gaijin! Gaijin!"
 _|_|_  -|- ||   __|__   /  / R90/6 pilot, DoD #0105   "Gaijin ha doko?"
|_|_|_|  |\-++-  |===|  /  /  Atheist & Proud          "Niichan ha gaijin."
 --|--  /| ||||  |___|    /\  (206) 842-2385/543-5762  "Chigau.  Gaijin ja nai.
  /|\    | |/\| _______  /  \ MRC@CAC.Washington.EDU    Omae ha gaijin darou"
 / | \   | |__|  /   \  /    \"Iie, boku ha nihonjin." "Souka. Yappari gaijin!"
Hee, dakedo UNIX nanka wo tsukatte, umaku ikanaku temo shiranai yo.

del@thrush.mlb.semi.harris.com (Don Lewis) (09/05/90)

In article <2350@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>In <6964@milton.u.washington.edu> mrc@Tomobiki-Cho.CAC.Washington.EDU
>(Mark Crispin) writes:
>
>>If "network I/O looks like local device I/O" under Unix then when the
>>h*ll do I have to worry about all the socket or streams crap?
>
>I think the confusion in this discussion is between reading and
>writing on the one hand and opening the connection on the other
>hand.
>
>Once a virtual circuit has been set up, the socket mechanism becomes
>transparent to the extent networking will allow.  Setting up the
>virtual circuit does require more steps than opening a device or file.
>I find this fairly understandable, because the BSD socket interface
>gives you LOTS of options, and it was designed to be independent of the
>underlying transport mechanism.
>
>>If I want to connect to port 0.143 on host 128.95.112.69, why can't I
>>do something like
>>  open ("/tcp/128.95.112.69-0.143",O_RDWR|O_CREAT,0);...
>
>Like somebody said, it would be nice if there was a library routine
>that would make this easy.  I suppose the open() system call could also
>do this, but then there might be too much functionality in a single
>system call, because it would have to understand all possible protocols
>and possibly accept additional parameters for the different types of
>sockets and connections that are possible.

If I have a local printer, I can send data to it by doing
	cat somefile >/dev/lp

Now, if the printer is on a terminal server somewhere, it would
sure would be nice to be able to do the same sort of thing.
	cat somefile >/dev/tcp/terminalserver:port
		or
	cat somefile >/dev/tcp/x.x.x.x-y.y

You could even send it to two devices using tee!

Specifically, you could use this for the lp= parameter in /etc/printcap
so that you don't have to play funky filter games.

The bottom line is that it should be possible to open connections with
fopen() so that applications don't have to be modified in order to
take advantage of this connectivity (assuming they don't rely on seeks
and wierd ioctls that don't make sense on a network connection).
--
Don "Truck" Lewis                      Harris Semiconductor
Internet:  del@mlb.semi.harris.com     PO Box 883   MS 62A-028
Phone:     (407) 729-5205              Melbourne, FL  32901

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/05/90)

Several people say that it's best to put everything into the filesystem.
But opening a file may not make sense for client-server applications.
Files may not be a very good abstraction for network communications in
general.

UNIX has from its conception given us an infinitely better solution:
passing references to files through descriptors instead of names.

So why don't we take advantage of this? Why don't we separate out
*opening* a file or *connecting* to a TCP server or *waiting* for a
connection into specialized programs? Why don't we have those programs
pass the suitably initialized descriptors to our processes? In other
words, why don't we take the modularity that we can get?

Answer: We can. Opening a file is done by your shell: $ <prog file.
Connecting to a server is done by authtcp: $ authtcp nyu smtp prog.
Serving connections is done by attachport: $ attachport -psmtp prog &.

Now, I admit that authtcp and attachport don't have perfect interfaces;
I'm developing a somewhat more general, much more portable client-server
framework. But they do the job. They take advantage of the modularity
that UNIX allows. And they'll be ported to the UNIX of the future.

---Dan

mrc@Tomobiki-Cho.CAC.Washington.EDU (Mark Crispin) (09/05/90)

In article <9009012315.AA08202@world.std.com> bzs@WORLD.STD.COM (Barry Shein) writes:
>I'm mixed on this issue. TOPS-20 had a file-system-like interface (was
>that BBN's TCP?) and, to be frank, I found it quite clumsy (tho
>interesting.) The string one passed to the open call started to look
>more and more like a long string of IBM/JCL and less and less like a
>file name as various options were added.


Hmm, I guess you never did much in JCL; I did, and believe me, the
name of TCP: files was a lot simpler!  The main bug in the TOPS-20
interface was that passive (listening), not active, was the default.

Anyway, the TOPS-20 filesystem TCP interface came from DEC.  The
original BBN interface was one that every socket hacker would love.
It implemented an entirely new set of system calls just for TCP,
passing around an entirely separate space of designators from files,
so every program that did network I/O had to have a completely
different I/O path just for TCP.  A gory mess.

DEC was originally going to rewrite it, but what they ended up doing
was writing a filesystem driver that used the BBN calls internally.
Eventually, there were some special hacks done to reduce the overhead,
but the underlying BBN mess remained.

However -- once the filesystem interface was available I don't know of
a single applications programmer who used the BBN calls.  Everybody
wrote using the TCP: device.  I'm quite familiar with all this as I
wrote most of the TOPS-20 applications-level TCP software.

Just you wait.  I'm sure that someone is going to end up inventing yet
another I/O schema for ISO.  And everyone will scream for something
that is backwards compatible with sockets or streams.

 _____   | ____ ___|___   /__ Mark ("Gaijin") Crispin  "Gaijin! Gaijin!"
 _|_|_  -|- ||   __|__   /  / R90/6 pilot, DoD #0105   "Gaijin ha doko?"
|_|_|_|  |\-++-  |===|  /  /  Atheist & Proud          "Niichan ha gaijin."
 --|--  /| ||||  |___|    /\  (206) 842-2385/543-5762  "Chigau.  Gaijin ja nai.
  /|\    | |/\| _______  /  \ MRC@CAC.Washington.EDU    Omae ha gaijin darou"
 / | \   | |__|  /   \  /    \"Iie, boku ha nihonjin." "Souka. Yappari gaijin!"
Hee, dakedo UNIX nanka wo tsukatte, umaku ikanaku temo shiranai yo.

andrew@megadata.mega.oz.au (Andrew McRae) (09/05/90)

In article <1990Sep5.020521.803@mlb.semi.harris.com>, del@thrush.mlb.semi.harris.com (Don Lewis) writes:
>In article <2350@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>>In <6964@milton.u.washington.edu> mrc@Tomobiki-Cho.CAC.Washington.EDU
>>(Mark Crispin) writes:
>>
>>>If I want to connect to port 0.143 on host 128.95.112.69, why can't I
>>>do something like
>>>  open ("/tcp/128.95.112.69-0.143",O_RDWR|O_CREAT,0);...
>
>Now, if the printer is on a terminal server somewhere, it would
>sure would be nice to be able to do the same sort of thing.
>	cat somefile >/dev/tcp/terminalserver:port

Perhaps a more structured approach to this whole problem is
to back out of the kernel altogether and use the same
paradigm as in some of the Research Unix kernels of a
user mode file system (a la the /proc filesystem); using a
UMFS would remove the complexity of mapping different
file names to network address away from the kernel into
user processes which could then use the BSD socket style
kernel calls to hide the messy details of network programming.

At least then the programs which want to access all those
neato network calls can do so, but for those programs that
want to open the network connection using a file name the
UMFS would then interpret the name accordingly. Then different
servers could be implemented to handle different protocols,
and services e.g.:

        fd = open("/dev/net/stream/cpu.xyz/lat", 2);

This could map to an entirely different protocol family (e.g. DECNet).

 or
        fd = open("/dev/net/tcp/2300/192.34.56.78", 2);

Links could be set up to map "/dev/net/printer" to
"/dev/net/tcp/termserver/printer"...

It should be easy to take skeleton UMFS network servers and
build specialised services (such as a nntp-service file etc.).
A mach-like kernel with good messaging may fit well here..

Whilst the comment that has been made that what most processes
want is a simple full duplex pipe-like stream (and the kind
of open that has been talked about will work OK), I find the more
common network programming I am involved with is using the
datagram facilities (sendto, recvfrom etc) to build distributed
services (especially real time stuff); using broadcasts and
finding out who sent you a data packet is important as well. I
hate to think what I would have to do if all I had was a read or write.

Andrew McRae			inet:	andrew@megadata.mega.oz.au
Megadata Pty Ltd,		uucp:	..!uunet!megadata.mega.oz.au!andrew
North Ryde  2113		Phone:	+61 2 805 0899
NSW    AUSTRALIA		Fax:	+61 2 887 4847

dls@mentor.cc.purdue.edu (David L Stevens) (09/05/90)

In article <9009012315.AA08202@world.std.com>, bzs@WORLD.STD.COM (Barry Shein) writes:
> As to David Stevens questions about file system semantics, what does
> "cd /dev/anydev" mean now? Nothing, you get back "Not a directory".
> In this mythical TCP you might get back something (e.g. some form of
> NFS done this way), or not. I don't see that as a serious problem.

	It's not the same analogy, which was my point. Crispin's example,
which you may not buy into, specifically uses "/"'s below the pseudo-device
boundary so that they become the exception to the syntax-directed pathname
translation that otherwise has the wonderfully dependable rule: "/ separates
directories."
	It's wrong because it's ugly and it doesn't fit with UNIX. Sure,
with a big enough hammer, you can make anything fit, but "/" is the wrong
delimiter. If the syntax doesn't follow the semantics, you've only created
a wart on a once-elegant system.
	As to the rest of your statement, I agree there is too much heat
and I'm not sure why, either. There may very well be a reasonable solution
that maps sockets onto a filesystem, but I see quite a few problems with
the Crispin solution, and (Mr Crispin,) your straw-man arguments, which
you make in your extremely creative interpretation of my article, don't
support your case. To me, anyway. You leave me with the impression, whether
justified or not, that you haven't thought through the details carefully,
and that's where all the mess comes up in the first place.
-- 
					+-DLS  (dls@mentor.cc.purdue.edu)

dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) (09/06/90)

Don Lewis writes:

     Now, if the printer is on a terminal server somewhere...
	     cat somefile >/dev/tcp/x.x.x.x-y.y

     Specifically, you could use this for the lp= parameter in
     /etc/printcap...

This would be nice.  A possible solution is to write a program "netsend":
     
     cat somefile | netsend tcp:x.x.x.x-y.y

Since printcap allows sending to a filter rather than a specific
device, the solution is general enough.

All we need now is for somebody to write it and send it to
comp.sources.misc.
--
Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com>
UUCP:  oliveb!cirrusl!dhesi

tinker@libai.UUCP (Don Tinker) (09/07/90)

>
>All we need now is for somebody to write it and send it to
>comp.sources.misc.
>--
>Rahul Dhesi <dhesi%cirrusl@oliveb.ATC.olivetti.com>
>UUCP:  oliveb!cirrusl!dhesi
>
>

I found by accident a program tcpf on uunet which I use for just this
purpose.


Don Tinker				tinker@ultra.com
Senior Field Support Engineer		{core}!ames!ultra!tinker
UltraNetwork Technologies Inc. 		(703) 821-8393

brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (09/07/90)

In article <2364@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
> This would be nice.  A possible solution is to write a program "netsend":
>      cat somefile | netsend tcp:x.x.x.x-y.y

It's been done! cat somefile | authtcp x.x.x.x y sh -c 'cat >&6'.

Specify -XR if you don't want RFC 931 security. Use multitee 0:6 instead
of sh -c 'cat >&6' if you have multitee.

> All we need now is for somebody to write it and send it to
> comp.sources.misc.

authtcp and attachport are in the auth package, which appeared in
c.s.unix volume 22. (multitee was also published in c.s.unix.)

---Dan

del@thrush.mlb.semi.harris.com (Don Lewis) (09/07/90)

In article <2364@cirrusl.UUCP> dhesi%cirrusl@oliveb.ATC.olivetti.com (Rahul Dhesi) writes:
>Don Lewis writes:
>
>     Now, if the printer is on a terminal server somewhere...
>	     cat somefile >/dev/tcp/x.x.x.x-y.y
>
>     Specifically, you could use this for the lp= parameter in
>     /etc/printcap...
>
>This would be nice.  A possible solution is to write a program "netsend":
>     
>     cat somefile | netsend tcp:x.x.x.x-y.y
>
>Since printcap allows sending to a filter rather than a specific
>device, the solution is general enough.

This is not enough if you need to use the `of' filter.  Lets say
you specify both the `if' and `of' filters and lpr a simple text
file.  Lpd opens the printer device, forks and execs a copy of
the `of' filter with its stdout connected to the printer and its
stdin connected to a pipe back to lpd.  Lpd then squirts the banner
down the pipe to the `of' filter followed by ^Y^A.  When the `of'
filter sees the ^Y^A, it flushes stdout and sends itself a STOP
signal.  Lpd sees the `of' filter stop and then forks and execs
a copy of the `if' filter which has its stdout connected to
the printer and its stdin connected to the file to be printed.
Once the `if' filter exits, lpd sends a CONT signal to the `of'
filter and writes either the banner for the next job or the trailer
string to it.  For different print file formats, substitute
the appropriate filter for the `if' filter.

If the particular device you are using needs the functionality
of the `of' filter, you can't just put a shell wrapper that
pipes its output to netsend because there is no way for the
`if' filter to make a connection to the printer as long as
the `of' filter is running (also, the link between `of' and
the printer may need to be bidirectional).  If you don't need
`of', you may be able to do this with `if', but you will
not be able the banner and trailer because lpd wants to
send these to the printer before/after running `if'.

There are possible workarounds using pty's or named pipes with
daemons on the other side or passing the fd to the socket through
unix domain sockets, but YUCK!  If the device is something wierd
and you don't have the source for the filters then you are in
pretty deep trouble.

Why should it take a wizard to switch a printer from a serial
port to a terminal server?
--
Don "Truck" Lewis                      Harris Semiconductor
Internet:  del@mlb.semi.harris.com     PO Box 883   MS 62A-028
Phone:     (407) 729-5205              Melbourne, FL  32901

tcs@BRL.MIL (Terry Slattery, SECAD) (09/07/90)

> This would be nice.  A possible solution is to write a program "netsend":
>      
>      cat somefile | netsend tcp:x.x.x.x-y.y
> 
> Since printcap allows sending to a filter rather than a specific
> device, the solution is general enough.

But it won't work for a postscript printer being driven from the
Transcript software.  Transcript wants to talk to the printer to
get status info, so the link needs to be bi-directional.

What you suggest has been done by cisco for their terminal servers
and is available from ftp.cisco.com:tcpf.c.

	-tcs