[Next][Prev] [Right] [Left] [Up] [Index] [Root]

Sockets

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. Currently sockets are only available on UNIX systems.

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.

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).

Subsections

Socket Creation

Socket(H, P : parameters) : MonStgElt, RngIntElt -> IOSocket
    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.
Socket( : parameters) : -> IOSocket
    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.
WaitForConnection(S) : IO -> IO
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.

Socket Properties

SocketInformation(S) : IO -> Tup, Tup
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.

Socket Predicates

IsServerSocket(S) : IO -> BoolElt
Returns whether S is a server socket or not.

Socket I/O

Due to the nature of the network, it takes significant time to transmit data from one machine to another. Thus when a read request is begun it may take some time to complete, usually because the data to be read has not yet arrived. Also, data written to a socket may be broken up into smaller pieces for transmission, each of which may take different amounts of time to arrive. Thus, unlike files, there is no easy way to tell if there is still more data to be read; the current lack of data is no indicator as to whether more might arrive.

When a read request is made on a socket, the available data is returned. If no data is currently available, then the process waits until some does becomes available, and returns that. (It will also return if the socket has been closed and hence no more data can be transmitted.) It does not continue trying to read more data, as it cannot tell whether or not there is some "on the way".

The upshot of all this is that care must be exercised as reads may return less data than is expected.

Read(S : parameters) : IO -> MonStgElt
    Max: RngIntElt                      Default: 0
Waits for data to become available for reading from S and then returns it as a string. If the parameter Max is set to a positive value then at most that many characters will be read. Note that less than Max characters may be returned, depending on the amount of currently available data.

If the socket has been closed then the special EOF marker string is returned.

ReadBytes(S : parameters) : IO -> SeqEnum
    Max: RngIntElt                      Default: 0
Waits for data to become available for reading from S and then returns it as a sequence of bytes (integers in the range 0..255). If the parameter Max is set to a positive value then at most that many bytes will be read. Note that less than Max bytes may be returned, depending on the amount of currently available data.

If the socket has been closed then the empty sequence is returned.

Write(S, s) : IO, MonStgElt ->
Writes the characters of the string s to the socket S.
WriteBytes(S, Q) : IO, SeqEnum ->
Writes the bytes in the byte sequence Q to the socket S. Each byte must be an integer in the range 0..255.

Example IO_Sockets (H3E12)

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

 [Next][Prev] [Right] [Left] [Up] [Index] [Root]

Version: V2.19 of Wed Apr 24 15:09:57 EST 2013