Network connections Isis software documentation

Network connections

This library contains functions for creating data connections between networked computers. Two protocols are supported: TCP and UDP. Like all other data endpoints, network connections are represented using standard Isis input and output ports.


TCP network connections

(tcp-listen portnumber) # returns server-port (tcp-accept server-port) # accepts a connection, returns port (tcp-open machinename portnumber) # opens connection to named machine (tcp-open address portnumber) # opens connection to explicit address # must be list of integers, like: [18 85 40 41] The TCP protocol is used for sending and receiving streams of data between two endpoints on the network. TCP is "reliable" in that data transmitted from one end is guaranteed not to get lost or arrive in a different order at the other end. More information can be found on the TCP man page (type man tcp at your shell prompt) or in the Addison-Wesley book series "TCP/IP Illustrated".

Isis provides basic TCP support with 3 functions. tcp-listen and tcp-accept are used for creating a "server" that others can connect to. tcp-open is used to connect to such a server that is already running on another machine.

tcp-listen causes the machine to listen for connections on a particular TCP port number. It returns an Isis port that should only really be used in tcp-accept, or in a pending call to see if there are any connections waiting to be accepted.

tcp-accept takes an Isis port that was obtained from tcp-listen, and it will not return until a connection has been established on that port. Once established, tcp-accept returns a new Isis port which may be used to read and write data on that connection.

tcp-open takes a machine name or explicit internet address in the form of a list of integers (such as [18 85 40 41]), and a port number. It establishes a TCP connection to that machine and port number, and returns an Isis port which may be used to read and write data on that connection.

If any errors occur, these functions will return Null.

Below is an example that creates a simple centralized database that other machines can connect to, query, and modify. It uses the Isis structure construct for storing the data. Other machines send requests in the form of lists. If the request list contains one item, it is considered to be a query, and the record in the database matching that key is sent back to the client. If the list contains two items, the record in the database is modified.

Here is the server program:

(set db (new-structure)) # set up a database structure (set lport (tcp-listen 1234)) # listen for connections (while True # loop forever (begin (set client (tcp-accept lport)) # accept a client connection (while (!= Null (set req (read client))) # read requests from client, until Null (switch (length req) # assume request was a list (1 (write client (db (req 0)))) # query database (2 (db (req 0) (req 1))))) # modify database (close client))) # close connection
Assuming the server is running on a machine named "satyricon", try running the following on different machines:
(set sport (tcp-open "satyricon" 1234)) (write sport [ "stefan" "E15-348" ]) (write sport [ "jacky" "E15-351" ]) (write sport [ "wad" "E15-355" ]) (close sport)
(set sport (tcp-open "satyricon" 1234)) (write sport ["wad"]) (set result (read sport)) (print "Wad is located in room " result newline) (close sport)


Multiple connection TCP servers

(create-multiserver portnumber) # returns multiserver object The multiserver object is useful when you want to create a server program that can handle messages from multiple TCP connections, where several connections might be open simultaneously, and clients can connect and disconnect whenever they want.

create-multiserver creates a multiserver listening on the given port number, and returns a procedure. Any time later when you call this procedure with no arguments, it will return a list of messages that have come in from the various connections that are open. The list will be empty if no messages have been received. The multiserver handles all the work of accepting new connections or closing stale connections.

Multiservers receive messages with the read command, so any messages sent to a multiserver must be transmitted with the write command (not write-string or write-raw).

Each message is a list of two things: [ originating-port raw-message ]. The originating-port is the port where this message came from, which you can use to respond to the client. The raw-message is the actual raw message that was received from this client.

You can configure and query the multiserver object by calling it with one or more arguments. Below is a list of valid commands. Assume the variable multiserv is a multiserver that has been created already.

  • (multiserv "wait" microseconds) returns immediately when there are messages waiting to be received. Otherwise it will until a message comes in or up to the specified number of microseconds before returning. This command can be important, because if your program is not doing any other work, it would be a waste of processor time to repeatedly call the multiserver asking for messages. This command allows you to delay for a certain amount of time until a message is received. You can then read the messages in the normal way.

  • (multiserv "count") returns the number of active connections the multiserver is tracking.

  • (multiserv "add" port) adds the given port to the list of ports the multiserver is tracking. Use this command if you want to add ports that you open yourself to the multiserver.

    Here is an example of a multiple connection database server. The server expects commands of the form ["store" key value] or ["retrieve" key]. When the retrieve command is received, a response is sent back to the corresponding port.

    (set database (new-structure)) (set multiserver (create-multiserver 1599)) (while True (begin (multiserver "wait" 1000000) (map (proc (message) (begin (set port (message 0)) (set command ((message 1) 0)) (switch command (begin ("store" (database ((message 1) 1) ((message 1) 2))) ("retrieve" (write (port (database ((message 1) 1))))))))) (multiserver))))


    UDP network connections

    (udp-open-output machinename portnumber) # open outgoing UDP connection to named machine (udp-open-output address portnumber) # open outgoing UDP connection to explicit address # should be list of integers, like: [18 85 40 41] (udp-open-input portnumber) # open incoming UDP connection The UDP protocol is used for sending "datagrams" between endpoints on the network. UDP is "unreliable" in that these datagrams are not guaranteed to arrive at all or in the same order that they are transmitted. More information can be found on the UDP man page (type man udp at your shell prompt) or in the Addison-Wesley book series "TCP/IP Illustrated".

    Isis provides basic UDP support with 2 functions. You can create an outgoing UDP connection to a particular machine and port number with udp-open-output. Conversely, udp-open-input creates an incoming UDP connection that will receive packets on the given port number. Both of these functions return an Isis port open for writing or reading respectively, or Null if there was a problem.

    VERY IMPORTANT: You can only use read-raw and write-raw to read and write data on UDP connections in Isis. Use of read, write, read-string or write-string result in undefined behavior. Further, UDP packets typically have a maximum size of 8192 bytes (depends on your network). If you attempt to read/write more than the maximum size, your packets will be truncated. Both the read-raw and write-raw functions will return the actual number of bytes read or written.

    Example

    Here are two programs that demonstrate sending and receiving audio with UDP. These programs access the low-level ALSA audio interface for recording and playing audio under Linux. They assume the same audio parameters and sound card type are in operation on both the source and destination machines. You can run both a sender and receiver on each endpoint to create a rudimentary Isis internet phone application. However, keep in mind that these programs are extremely basic examples. They do not check if audio packets are dropped or received out of order, which will result in garbled audio if network congestion is present. See if you can alter the programs to handle these situations gracefully by adding a packet "header" with a counter and other information.

  • UDP audio sender
  • UDP audio receiver