hedrick@athos.rutgers.edu (Charles Hedrick) (08/28/90)
Before we got diverted, the original question was whether code that needs to access the network should use sockets or streams. Since then, I've looked up the streams documentation in SunOS 4.1. I'm going to assume that's typical of what streams is like, but of course that could be wrong. So take this with a grain of salt. In my opinion, if you want to support a full range of systems, you're going to have to deal with both sockets and streams. So that's not the basic design choice. It's also not a big issue anyway. All network code that I've seen has subroutines for doing the low-level network operations such as openning connections. These are not complex subroutines. Maybe half a page each. They just do the right combination of socket, bind, connect, etc. So the streams version is going to have another version of the subroutine to open a connection, that uses t_bind and t_connect instead of bind and connect. Big deal. Similarly, data transfer subroutines can use send and recv for Berkeley and t_snd and t_rcv for the streams version. The real issue seems to be not this, but the problem that streams doesn't fit the normal Unix view of I/O. At least in SunOS 4.1, you can't do read and write on a stream. Thus the special t_snd and t_rcv calls for I/O. Sockets allow you to use either special send and recv calls, which allow more detailed control over network-level handling, or normal read and write. But SunOS provides a streams module you can push that gives you read and write. It can't deal with out of band data, but if you know your application doesn't use OOB, it might be usable. It seems clear that you can get streams/sockets compatibility by doing everything with subroutines and supplying streams and sockets versions for everything. But there are two questions that can really only be answered by people who have experience with using streams: (1) What is the performance penalty for using the read/write interface in streams? With sockets, the send/recv interface is at the same level as the read/write interface, so there's no reason to expect any performance penalty for using read and write. Indeed it's very rare that you see programs using send and recv. This allows you to use things like printf, and to set primary input or output to a socket. With a stream, if you want to do this, you have to push on the read/write interface. I could imagine ways of implementing it that wouldn't result in any more overhead than doing the low-level I/O, but there's no way to know whether this will happen in real implementations other than trying it. If read/write turns out to be unacceptable under streams, then you'll need to go to the approach of using subroutines or macros for your low-level code, so that you can supply both socket and streams versions. (By the way, the original ATT claim was that sockets were a terrible wart on Unix, and streams were "clean". I'm not sure what -- if anything -- that meant. It seems to me that sockets makes network I/O look a lot more like normal file I/O than streams do.) (2) Is it a good idea to use the "sockets library"? Comments have been made about both overhead and portability. Again, this is an issue that only experience can settle. Most applications of sockets that I've seen use read and write. In this case, all you need the sockets library for is to open and close the connection. Once it's open, you're going to use read and write directly, which will not need to pass through any sockets emulation. So this seems to reduce to the previous question, of whether the read/write interface to streams has too much overhead. Whether it makes sense to use the sockets library for opening and closing seems to reduce to the issue of how good the sockets libraries are and how compatible the streams implementations are. Clearly streams itself is just a framework. It's only the actual device drivers and streams modules that determine whether two implementations look at all alike. One could imagine a world in which each streams implementation looks different, but all their socket emulation libraries are fairly compatible. One could also imagine a world in which everyone used the same streams code, but the socket libraries are very flaky. In the first case, you'd be better off to use sockets, in the second you'd be better off to use streams. Since it's hard to get reliable information on any of these topics, I think I'd make sure that my code is designed in such a way that you can handle either case. That is, I'd run all network operations -- opening, closing, and actual I/O -- through low-level subroutines or macros that are designed so you can implement them with either sockets or streams.
henry@zoo.toronto.edu (Henry Spencer) (08/28/90)
In article <Aug.27.17.09.46.1990.14447@athos.rutgers.edu> hedrick@athos.rutgers.edu (Charles Hedrick) writes: >... (By the way, the original >ATT claim was that sockets were a terrible wart on Unix, and streams >were "clean". I'm not sure what -- if anything -- that meant. It >seems to me that sockets makes network I/O look a lot more like normal >file I/O than streams do.) It is important to distinguish "streams" (Dennis Ritchie's term for his revised non-block-device i/o system) from "STREAMS" (what AT&T put into System V). Dennis's streams cleaned up a lot of mess, and improved performance to boot. But as Dennis is rumored to have said, "`streams' means something different when shouted". The way to do i/o on Dennis's streams was with "read" and "write". Network i/o, in general, looked *exactly* like local device i/o. This is the way it should be, unlike what both Berkeley and AT&T have done (both have reluctantly conceded that most people want to use "read" and "write" and have made that work, but their hearts were clearly elsewhere). -- TCP/IP: handling tomorrow's loads today |Henry Spencer at U of Toronto Zoology OSI: handling yesterday's loads tomorrow| henry@zoo.toronto.edu utzoo!henry
guy@auspex.auspex.com (Guy Harris) (08/29/90)
>The real issue seems to be not this, but the problem that streams >doesn't fit the normal Unix view of I/O. At least in SunOS 4.1, you >can't do read and write on a stream. Well, yes, you can, actually. You have programs that do "read()" and "write()" on terminals under SunOS 4.x, right? If so, they're doing "read()" and "write()" on streams.... What you can't do in SunOS 4.1 - nor in the S5R3 systems from which much of that code came - is "read()" and "write()" on *TLI* streams that don't have the "tirdwr" module pushed atop them. That module, which you mention, actually comes from S5R3. In S5R[34], streams isn't really the equivalent of sockets, streams *plus TLI* is. (I wouldn't be at all surprised to find that in the Research UNIX streams code, you *can* do "read()" and "write()" on streams used for network connections. I don't know if this is the case, but I wouldn't be surprised if it were....)
stanonik@NPRDC.NAVY.MIL (Ron Stanonik) (08/29/90)
Wollongong's win 3b implementation of tcp/ip (on our 3b2's running sysVr3) seems to only push tirdwr for the accept socket call. We've installed a couple of bsd programs (syslog and lpr), which use read/write and seem to work just fine. Anybody know what tirdwr does? Gather/scatter packets to satisfy the read/write size argument? Some oob handling? Ron Stanonik stanonik@nprdc.navy.mil ps. Is there anyway to get a list of all the modules pushed onto a stream. I_LOOK only lists the top most module.
jbvb@FTP.COM (James B. Van Bokkelen) (08/29/90)
The way to do i/o on Dennis's streams was with "read" and "write". Network i/o, in general, looked *exactly* like local device i/o. This is the way it should be, unlike what both Berkeley and AT&T have done (both have reluctantly conceded that most people want to use "read" and "write" and have made that work, but their hearts were clearly elsewhere). I would say rather that using read/write on network connections is the way most people would *like* it to be. The reality is that on most systems the local filesystem is a pretty tame beast compared to a network connection. Unless the OS/language combination's read/write was designed with network connections in mind (which means boolean flag arguments and wide variations in behaviour depending on them), use of read/write is likely to result in a cantankerous and unreliable network application... James B. VanBokkelen 26 Princess St., Wakefield, MA 01880 FTP Software Inc. voice: (617) 246-0900 fax: (617) 246-0901
henry@zoo.toronto.edu (Henry Spencer) (08/31/90)
In article <9008291448.AA14069@ftp.com> jbvb@ftp.com writes: > The way to do i/o on Dennis's streams was with "read" and "write". > Network i/o, in general, looked *exactly* like local device i/o. This > is the way it should be... > >I would say rather that using read/write on network connections is >the way most people would *like* it to be. The reality is that on >most systems the local filesystem is a pretty tame beast compared to >a network connection. Unless the OS/language combination's >read/write was designed with network connections in mind (which means >boolean flag arguments and wide variations in behaviour depending on >them), use of read/write is likely to result in a cantankerous and >unreliable network application... Only if you have a cantankerous and unreliable network. :-) True, the network interface is more complex than most device interfaces (although whether it is more complex than the tty interface, in particular, is a debatable point!)... but most applications don't care. They just want to open a connection to service X on machine Y and reliably send bits back and forth. The complexities have to be present for the occasional sophisticated customer, but the simple customer shouldn't have to worry about them. The Unix tty interface is quite complex, but most programs can ignore most of it -- if they want to print an error message, they just say "fprintf(stderr, ..." and it works. That's the way the network interface should be too: some simple way to open a connection (I find it impossible to comprehend why 4BSD doesn't have an open-connection-to- service-X-on-machine-Y library function, given how stereotyped and how messy this job is), read/write for i/o, close for shutdown (and ioctl for option setting etc. for those who care). That's all most customers want. The networking facilities in Eighth/Ninth/Tenth Edition Unix within Bell Labs are existence proofs that this approach can and does work. -- TCP/IP: handling tomorrow's loads today| Henry Spencer at U of Toronto Zoology OSI: handling yesterday's loads someday| henry@zoo.toronto.edu utzoo!henry
jbvb@FTP.COM (James B. Van Bokkelen) (08/31/90)
.... The complexities have to be present for the occasional sophisticated customer, but the simple customer shouldn't have to worry about them. The Unix tty interface is quite complex, but most programs can ignore most of it -- if they want to print an error message, they just say "fprintf(stderr, ..." and it works. That's the way the network interface should be too: some simple way to open a connection (I find it impossible to comprehend why 4BSD doesn't have an open-connection-to-service-X-on- machine-Y library function, given how stereotyped and how messy this job is), read/write for i/o, close for shutdown (and ioctl for option setting etc. for those who care). That's all most customers want. I see where our viewpoints differ: I am selling applications to end-users, and I intend to support them. Most of the end-users who use our Development Kit for one-off or in-house applications are probably quite satisfied with open/read/write/close. However, I am careful to advise any OEMs who develop for resale to pay close attention to the flags and error codes... James B. VanBokkelen 26 Princess St., Wakefield, MA 01880 FTP Software Inc. voice: (617) 246-0900 fax: (617) 246-0901
sklower@ernie.Berkeley.EDU (Keith Sklower) (09/01/90)
In article <1990Aug28.162400.17811@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes: >The way to do i/o on Dennis's streams was with "read" and "write". >Network i/o, in general, looked *exactly* like local device i/o. This >is the way it should be, unlike what both Berkeley and AT&T have done >(both have reluctantly conceded that most people want to use "read" >and "write" and have made that work, but their hearts were clearly >elsewhere). I find this inaccurate, partronizing and tiresome. I have worked around Berkeley since 1978 and although was not a member of the actual unix group in 1982 while TCP was being incorporated, attended their meetings and seminars. I assure you that it was the design goal then, that only ``sophisticated process'' would need a more elaborate mechanism to establish a network connection, but that once having established one, that it should be usable as a completely ordinary file descriptor by ``naive'' processes like the date command, using read and write, and that the file descriptor should be inherited by the normal unix means (fork & exec). It sounds to me like Henry is attempting to rewrite history (for his own possibly political motives).
pcg@cs.aber.ac.uk (Piercarlo Grandi) (09/03/90)
On 31 Aug 90 19:48:37 GMT, sklower@ernie.Berkeley.EDU (Keith Sklower) said:
sklower> In article <1990Aug28.162400.17811@zoo.toronto.edu>
sklower> henry@zoo.toronto.edu (Henry Spencer) writes:
spencer> The way to do i/o on Dennis's streams was with "read" and "write".
spencer> Network i/o, in general, looked *exactly* like local device i/o.
Note that with the most recent developments of UNIX (FSS) read() and
write() no longer mean much, except 'move data from/to the kernel'; they
have become just a way to add new system calls, using a file like style
of interface. The semantics of write() and read() have become very very
loose. What does read/write mean on /dev/proc? Something highly non
obvious.
spencer> This is the way it should be, unlike what both Berkeley and
spencer> AT&T have done (both have reluctantly conceded that most people
spencer> want to use "read" and "write" and have made that work, but
spencer> their hearts were clearly elsewhere).
And for good reason! read() and write() on file descriptors is not the
most amusing interface. It is much more convenient to have IPC style
access to files, e.g. Accent with its ports, than viceversa, unless we
are so wedded to UNIX that we cannot change (probably true, vide failure
of Accent to get accepted, and then success of Mach, which is a Unix
like imitation of it).
Frankly, the "everything is a file" way of achieving connectability is
not the best abstraction, because you want to connect to active
services, not just to passive storage. Straining a file model to include
"active" files is a bit inelegant.
"everything is a socket" or equivalently "everything is a process" (even
files!) are much better; "everything is a file system", the technology
used in recent research Unixes or PLAN/9 is a way to get as abstraction
a more active thing than a file, works better than "everything is a
file", yes, but requires a large suspension of disbelief, and assumes
that we really want the Unix directory tree model for all name service,
which may not be a terribly good choice either.
e.g. as in having an internet filesystem type, and doing
something like
fd = open("/dev/internet/lcs.mit.edu/echo.udp",...);
/*or*/ fd = open("/dev/internet/edu/mit/lcs/119.tcp",...);
sklower> I find this inaccurate, partronizing and tiresome. I have
sklower> worked around Berkeley since 1978 and although was not a member
sklower> of the actual unix group in 1982 while TCP was being
sklower> incorporated, attended their meetings and seminars.
Ahh. Incidentally, I would like to observe that I have *never* seen an
implementation of BSD sockets and TCP. The only ones that circulate are
extremely limited and rigid subsets. Since you have been around UCB for
so long, can you tell us why there is no (full) implementation of BSD
sockets? E.G. where are user domain type filedescriptors?
About compatibility between IPC and normal file I/O:
sklower> I assure you that it was the design goal then, that only
sklower> ``sophisticated process'' would need a more elaborate mechanism
sklower> to establish a network connection, but that once having
sklower> established one, that it should be usable as a completely
sklower> ordinary file descriptor by ``naive'' processes like the date
sklower> command, using read and write, and that the file descriptor
sklower> should be inherited by the normal unix means (fork & exec).
Uhm. Precisely. And 'wrappers', one of the features of BSD sockets, were
designed to make such compatibility absolute. Why nobody has ever
implemented them?
sklower> It sounds to me like Henry is attempting to rewrite history
sklower> (for his own possibly political motives).
I actually think that he may innocent, but he *is* attempting to rewrite
history, in a way different from what you say; on BSD it actually
happens that read/write on sockets is the same as on files, but because
they changed the specification of read/write on files.
The only difference with send/rcv is that sendmsg/rcvmsg allow
out-of-band, and passing file descriptors, which make no sense with
read/write to a file, but the distance from traditional read/write is
larget than that.
--
Piercarlo "Peter" Grandi | ARPA: pcg%uk.ac.aber.cs@nsfnet-relay.ac.uk
Dept of CS, UCW Aberystwyth | UUCP: ...!mcsun!ukc!aber-cs!pcg
Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk
guy@auspex.auspex.com (Guy Harris) (09/03/90)
(Not particularly TCP/IP oriented at this point....) >>> ps. Is there anyway to get a list of all the modules pushed onto >>> a stream. I_LOOK only lists the top most module. >> >>Not in V.3. > >Actually it is not quite that bad. You should have an idea of all the >possible modules that COULD be on a given stream (not many). It is then >trivial to write a little program which uses I_FIND to see if the module >is on the stream. That'll tell you *which* modules are on the stream, but it won't tell you where they are on the stream. If you want that, you need something such as S5R4's I_LIST.
lars@spectrum.CMC.COM (Lars Poulsen) (09/05/90)
In article <1990Aug28.162400.17811@zoo.toronto.edu> henry@zoo.toronto.edu (Henry Spencer) writes: >spencer> The way to do i/o on Dennis's streams was with "read" and "write". >spencer> Network i/o, in general, looked *exactly* like local device i/o. > >spencer> This is the way it should be, unlike what both Berkeley and >spencer> AT&T have done (both have reluctantly conceded that most people >spencer> want to use "read" and "write" and have made that work, but >spencer> their hearts were clearly elsewhere). In article <PCG.90Sep2194524@athene.cs.aber.ac.uk> pcg@cs.aber.ac.uk (Piercarlo Grandi) writes: >And for good reason! read() and write() on file descriptors is not the >most amusing interface. It is much more convenient to have ... [features] The problem is larger than that. As commercial programmers have often said, unix read() and write() is not a very good interface for files, either. It is a good interface for SIMPLE TEXT files, and very little else. Having a guaranteed subset of compatible functionality has allowed very productive use of the "building block" philosophy. Having a way to specify a remote conenctions "as if" it were a filename would allow more things to be prototyped with simple shell scripts and pipelines. On the other hand, great flexibility leads to a loss of device independence, witness VMS' proliferation of pseudo-device drivers as an example of where the path of customized interfaces may take us. -- / Lars Poulsen, SMTS Software Engineer CMC Rockwell lars@CMC.COM
henry@zoo.toronto.edu (Henry Spencer) (09/05/90)
In article <38584@ucbvax.BERKELEY.EDU> sklower@ernie.Berkeley.EDU.UUCP (Keith Sklower) writes: >>...the way it should be, unlike what both Berkeley and AT&T have done >>(both have reluctantly conceded that most people want to use "read" >>and "write" and have made that work, but their hearts were clearly >>elsewhere). > >I find this inaccurate, partronizing and tiresome. I have worked around >Berkeley since 1978 and although was not a member of the actual unix group >in 1982 while TCP was being incorporated, attended their meetings and >seminars. I wasn't there; all I got to do was read the resulting documents. Some of which come over with a very strong air of "well, if you want to do it right, you will of course use our 57 new system calls, but we grudgingly admit that read/write will work if you insist on being backward". -- TCP/IP: handling tomorrow's loads today| Henry Spencer at U of Toronto Zoology OSI: handling yesterday's loads someday| henry@zoo.toronto.edu utzoo!henry
henry@zoo.toronto.edu (Henry Spencer) (09/05/90)
In article <9008311500.AA12356@ftp.com> jbvb@ftp.com writes: > ...That's all most customers want. > >I see where our viewpoints differ: I am selling applications to end-users, >and I intend to support them. Most of the end-users who use our Development >Kit for one-off or in-house applications are probably quite satisfied with >open/read/write/close. However, I am careful to advise any OEMs who develop >for resale to pay close attention to the flags and error codes... I was writing from the down-in-the-wires viewpoint, where *any* user process is a customer. And on the whole, I remain unrepentant. :-) It should be possible to use open/read/write/close, with (say) perror when something goes wrong, without major problems, assuming that error-message-and-die is a reasonable thing to do on failure. A requirement for fault tolerance does require closer attention to error handling, as in non-networked code. Also as in non-networked code, a requirement for carefully optimized use of system resources requires attention to flags and details. And anyone building production code should be aware of the grubby details, so that he can recognize the one case in a hundred where some of them are relevant. However, I continue to believe that what most applications want to see is a reliable bidirectional pipe, perhaps set up in slightly odd ways but thereafter used via read/write/close, with invisible recovery from transient problems and a suitable errno value on hard failure. The resemblance to a Unix file is not accidental. :-) -- TCP/IP: handling tomorrow's loads today| Henry Spencer at U of Toronto Zoology OSI: handling yesterday's loads someday| henry@zoo.toronto.edu utzoo!henry
bzs@WORLD.STD.COM (Barry Shein) (09/06/90)
I think we're all looking at this in far too narrow a context. There are many issues that are being hand-waved (note, anyone who assumes I believe one way or the other on this issue please send me my decision as I haven't received it yet.) For example, when I address something that reaches out into, say, network name space, where does my request go? Does it go to a specialized driver that takes care of things like DNS resolution? Does it get handed back up to a user-level process? What? I still think the terminal example (open("/dev/tty/9600/even/noecho",...) was a good one. Someone sent me mail saying "oh, that's just ioctl()'s". What magic! Sockets are bad, ioctls are good, such power in a name. The real issue is: A) Are we trying to simplify/generalize the *user* interface so most any network/etc operation can be specified in a string, wherever a file name is expected? or B) Are we trying to simplify/generalize the *programmer* interface so they don't have to know about those nasty socket calls? Careful, I believe those two goals can be very much in conflict. I also don't believe that everyone discussing this issue on this list falls into the same camp. So we're having definite communications problems, state your objectives! -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
pcg@cs.aber.ac.uk (Piercarlo Grandi) (09/13/90)
On 4 Sep 90 17:29:23 GMT, lars@spectrum.CMC.COM (Lars Poulsen) said: lars> In article <1990Aug28.162400.17811@zoo.toronto.edu> lars> henry@zoo.toronto.edu (Henry Spencer) writes: spencer> The way to do i/o on Dennis's streams was with "read" and spencer> "write". Network i/o, in general, looked *exactly* like local spencer> device i/o. If you want to keep UNIX like semantics. Unfortunately you really want to do typed data, if only to include passing file descriptors, and OOB signaling, and these do not fit well with traditional UNIX style interfaces. spencer> This is the way it should be, unlike what both Berkeley and spencer> AT&T have done (both have reluctantly conceded that most people spencer> want to use "read" and "write" and have made that work, but spencer> their hearts were clearly elsewhere). lars> In article <PCG.90Sep2194524@athene.cs.aber.ac.uk> lars> pcg@cs.aber.ac.uk (Piercarlo Grandi) writes: pcg> And for good reason! read() and write() on file descriptors is not pcg> the most amusing interface. It is much more convenient to have ... pcg> [features] Hey, I take exception to the [features] summary -- I was describing not a set of extra features, but a completely different philosophy based on communication with active entities represented by IPC ports. An alternative to the UNIX style file descriptors to access passive files. It can be as simple and terse as the current UNIX style. lars> The problem is larger than that. As commercial programmers have lars> often said, unix read() and write() is not a very good interface lars> for files, either. It is a good interface for SIMPLE TEXT files, lars> and very little else. Uhm. Here we differ. The UNIX style of accessing file is excellent for any type of file, because any type of file can be mapped onto untyped byte arrays (a.k.a. virtual memory segments), by the use of suitable library procedures. Unfortunately non storage like entities are not easily mapped onto untyped byte arrays. lars> Having a guaranteed subset of compatible functionality has allowed lars> very productive use of the "building block" philosophy. Having a way to lars> specify a remote conenctions "as if" it were a filename would allow more lars> things to be prototyped with simple shell scripts and pipelines. The problem is that modeling everything as a passive entitity is far less flexible than modling everything as an active entity. -- Piercarlo "Peter" Grandi | ARPA: pcg%uk.ac.aber.cs@nsfnet-relay.ac.uk Dept of CS, UCW Aberystwyth | UUCP: ...!mcsun!ukc!aber-cs!pcg Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk