Magma provides a file I/O object for interacting with external files.
The string returned by IOType for such an object is "file".
Note that there are also several intrinsics that interact with files using
the file name alone (for examples, see the sections on printing and input).
Magma provides a pipe I/O object for interacting with external programs.
The string returned by IOType for such an object is "pipe".
Note that there are also some intrinsics that interact with programs using
the program name alone (for examples, see the sections on input and
system calls).
Pipes are not currently available on Windows platforms.
This will be addressed in a future release.
We write a function which returns the current time as 3 values:
hour, minutes, seconds. The function opens a pipe to the UNIX
date command and applies regular expression matching to the
output to extract the relevant fields.
> function GetTime()
> I := POpen("date", "r");
> date := Read(I);
> _, _, f := Regexp("([0-9][0-9]):([0-9][0-9]):([0-9][0-9])", date);
> h, m, s := Explode(f);
> return h, m, s;
> end function;
> h, m, s := GetTime();
> h, m, s;
14 30 01
> h, m, s := GetTime();
> h, m, s;
14 30 04
Magma provides a socket I/O type for communicating over the network.
The string returned by IOType for such an object is "socket".
Sockets may be used to establish communication channels between machines
on the same network. Once established, they can be read from or written
to in much the same ways as more familiar I/O constructs like files.
One major difference is that the data is not instantly available, so the
I/O operations take much longer than with files.
Strictly speaking, a socket is a communication endpoint whose
defining information consists of a network address and a port number.
(Even more strictly speaking, the communication protocol is also part of
the socket. Magma only uses TCP sockets, however, so we ignore this
point from now on.)
The network address selects on which of the available network interfaces
communication will take place; it is a string identifying the machine
on that network, in either domain name or dotted-decimal format.
For example, both "localhost" and "127.0.0.1" identify the
machine on the loopback interface (which is only accessible from the
machine itself), whereas "foo.bar.com" or "10.0.0.3" might
identify the machine in a local network, accessible from other machines
on that network.
Currently only IPv4 addresses are supported.
The port number is just an integer that identifies the socket on a
particular network interface. It must be less than 65 536.
A value of 0 will indicate that the port number should be chosen
by the operating system.
There are two types of sockets, which we will call client sockets and
server sockets.
The purpose of a client socket is to initiate a connection to a
server socket, and the purpose of a server socket is to wait for
clients to initiate connections to it.
(Thus the server socket needs to be created before the client can
connect to it.)
Once a server socket accepts a connection from a client socket, a
communication channel is established and the distinction between
the two becomes irrelevant, as they are merely each side of a
communication channel.
In the following descriptions, the network address will often be
referred to as the host. So a socket is identified by a
(host, port) pair, and an established communication channel
consists of two of these pairs:
(local-host, local-port), (remote-host, remote-port).
LocalHost: MonStgElt Default: none
LocalPort: RngIntElt Default: 0
Attempts to create a (client) socket connected to port P of host H.
Note: these are the remote values; usually it does not matter
which local values are used for client sockets, but for those rare
occasions where it does they may be specified using the parameters
LocalHost and LocalPort.
If these parameters are not set then suitable values will be chosen by
the operating system.
Also note that port numbers below 1 024 are usually reserved for
system use, and may require special privileges to be used as the
local port number.
LocalHost: MonStgElt Default: none
LocalPort: RngIntElt Default: 0
Attempts to create a server socket on the current machine, that
can be used to accept connections. The parameters LocalHost and
LocalPort may be used to specify which network interface and port
the socket will accept connections on; if either of these are not set
then their values will be determined by the operating system.
Note that port numbers below 1 024 are usually reserved for
system use, and may require special privileges to be used as the
local port number.
This may only be used on server sockets. It waits for a connection
attempt to be made, and then creates a new socket to handle the
resulting communication channel. Thus S may continue to be used
to accept connection attempts, while the new socket is used for
communication with whatever entity just connected.
Note: this new socket is not a server socket.
This routine returns the identifying information for the socket as
a pair of tuples. Each tuple is a {<host, port>} pair ---
the first tuple gives the local information and the second gives the
remote information. Note that this second tuple will be undefined for
server sockets.
Returns whether S is a server socket or not.
Here is a trivial use of sockets to send a message from one Magma
process to another running on the same machine.
The first Magma process sets up a server socket and waits for
another Magma to contact it.
> // First Magma process
> server := Socket(: LocalHost := "localhost");
> SocketInformation(server);
<localhost, 32794>
> S1 := WaitForConnection(server);
The second Magma process establishes a client socket connection
to the first, writes a greeting message to it, and closes the socket.
> // Second Magma process
> S2 := Socket("localhost", 32794);
> SocketInformation(S2);
<localhost, 32795> <localhost, 32794>
> Write(S2, "Hello, other world!");
> delete S2;
The first Magma process is now able to continue; it reads and
displays all data sent to it until the socket is closed.
> // First Magma process
> SocketInformation(S1);
<localhost, 32794> <localhost, 32795>
> repeat
> msg := Read(S1);
> msg;
> until IsEof(msg);
Hello, other world!
EOF
A server socket cannot tell which user is connecting to it.
(Indeed, the very concept is not well-defined if the connection is made
from another machine.)
Thus it is possible for someone on another machine on the same network
to connect to "your" socket, whether by accident or otherwise, and
this cannot be directly distinguished from an intended connection from
a process under your control.
Problems may then arise if the data from this unexpected connection does
not meet whatever requirements your code has.
If you are reasonably sure that no-one else with access to your machine
or its network will act in such a way, then you can simply use the
socket functions as described above.
Otherwise, some kind of authentication process would be desirable.
A simple method is to require that client connections first send some
data known only to the server, and have the server reject connections
which do not do so.
A more robust and convenient version of authentication is being worked
upon, and will appear in a later patch release.
[Next][Prev] [Right] [Left] [Up] [Index] [Root]