TCP library

Martin Wierich martinw@cs.kun.nl
Thu, 4 Feb 1999 11:14:42 +0100


Hi there,

Our approach differs from the Unicon approach, because we give our channels
types.

The type constructor for channels has as it's argument the type of the messages
being sent/received. We use uniqueness, because Clean is a functional language:
e.g. sending on a channel alters the "contents" of a channel. This is similar
to writing into a (unique) file. We define classes for the operations on
channels:

  class Receive ch
  where
    receive :: !*(*ch .msg) !*env -> (!.msg, !*(*ch .msg), !*env) |
ChannelEnv env
    ...

  class Send ch
  where
    send :: !*(*ch .msg) !.msg !*env -> (!*(*ch .msg), !*env)     |
ChannelEnv env
    ...

I will talk about the env parameter later.

Now we can instanciate these classes for using TCP or UDP. The type of the
messages
would be byte sequence ("ByteSeq"). A further instance of Receive is a
"TCP_Listener",
which is listening on a port. The message type contains a TCP channel, so
receiving
on a listener will accept a connection request, similar to Unicon.

We also can build arbitrary protocols on top of TCP or UDP by creating new
instances,
perhaps HTTP channels or FTP channels. It is planned to provide "dynamic
channels".
The message type of these channels is the Dynamic type (still to come in
Clean version
2.0). One will be able to transform (nearly) any expression in a Clean
program into
a Dynamic object, send it via a dynamic channel and via the internet to
another Clean
program, which can pattern match the received dynamic object on the type it
expects
to get. The result will be a typed Clean object on which all correctly
typed functions
can be applied. Even more, the dynamic can contain functions itself ! In
this way
it's very easy to communicate data and programs between distributed Clean
programs.

It turned out to be an advantage to make a distinction between "send
channels" and
"receive channels". So two unique objects are created for one TCP
connection. This
might look strange for people, who have experience with other TCP APIs, but
it fits
very good together with Clean's uniqueness type system. So here are two
instances:

instance Receive TCP_RChannel_
instance Send    TCP_SChannel_

The env parameter above eases the specification of order of evaluation. E.g. in

  # (sendChannel,world) = send sendChannel (toByteSeq "Ik zeg Hoi") world
    (receivedMessage,receiveChannel,world) = receive receiveChannel world

it is ensured, that the send happens before the receive.

The following function listens on port 1888, accepts a connection, receives
from that
connection and sends the data back.

Start world
    # (_,mbListener,world)              = openTCP_Listener 1888 world
      (mbTCPDuplexChan, listener, world)= receive (fromJust mbListener) world
      (_,{sChan,rChan})                 = fromJust mbTCPDuplexChan
      world                             = closeChan listener world
      (receivedData, rChan, world)      = receive rChan world
      (sChan, world)                    = send sChan receivedData world
      world                             = closeChan sChan world
      world                             = closeChan rChan world
    = world

greetings
  Martin Wierich

--------------------------------------------------------------------------------
--
Richard wrote

>	From: 	Martin Wierich[SMTP:martinw@cs.kun.nl]
>	Sent: 	Wednesday, January 27, 1999 11:25 AM
>
>	In about two month, the Object IO library will contain a TCP interface.
>	It will contain a synchronous and an asynchronous part.
>
>Before you release anything, I'd ask you to look at the Unicon socket
>interface.  Briefly:
>	open(addr, "na")	Listen on a TCP socket (as a server)
>	open(addr, "n")		Connect to a TCP socket (as a client)
>	open(addr, "nau")	Listen on a UDP socket (as a server)
>	open(addr, "nu")	Connect to a UDP socket (as a client)
>where addr is
>	host.name:port		port @ remote host
>	:port			port @ local host
>	file/name		UNIX domain socket, TCP only
>open() is also used for opening ordinary files and devices;
>with the "n" mode it returns streams that can be treated like other
>non-seekable streams and are closed with the same close() as other stream.
>
>There are also send() and receive() procedures for sending and receiving
>datagrams.
>
>gethost(host) returns an alias/address record for the specified host;
>gethost() is effectively a stream of aliases/addresses records.
>getserv(service, protocol) returns a name/aliases/port/protocol
>record for that service; getserv() is effectively a stream of these
>records.
>
>I bring this up because the Unicon interface
>- has already had a *lot* of discussion and design
>- is remarkably straightforward to use
>- has been or is in the process of being ported to Windows;
>  as far as I know the only thing that gave trouble is fork(),
>  which the TCP interface doesn't depend on.
>
>See
>    http://www.drones.com/unicon/