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:
Assuming the server is running on a machine named "satyricon", try running the following on different machines:
(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
(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)
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.
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))))
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.
UDP audio sender UDP audio receiver