Each instance, or network object, can be used to communicate with one cooperating LYMB process (called the "partner process" herein). Thus a "point-to-point" network connection is established between two network objects in cooperating LYMB processes (but each process may establish many such connections).
A typical connection between processes A and B is established by process A doing an "establish", followed by a "connect" by B and an "accept" by A in either order. After the connection is complete, "send" and/or "read" can be executed by both processes, effectively implementing bidirectional peer-to-peer message-passing.
auto_establish! establishes a network socket on first available port, starting at port 1024.
portnum? returns the port number of an established or connected socket. This is either the argument to a previous "establish:" message, the second argument to a previous "connect:" message, or the port number chosen as a result of an "auto_establish!" message.
connect:(hostname, portnum) connect to another LYMB process running on network node hostname that has establish'ed a socket with number portnum.
accept! when executed by a network object that has done an "establish", accepts any "connect" from another LYMB process. When both the accept and the connect have rendez-vous'ed, the two processes can begin communicating with each other. The process doing the accept! remains blocked until the connection is completed. The "accept()" system call is invoked on the socket returned by "accepting_socket?". Subsequent communication is done over the socket returned by "socket?". If "accept!" is sent to a network object in connected state (status=2), the previous communication socket is lost. Multiple accepts can be done by a network object, but the programmer is responsible for saving the current communication socket descriptor (returned by "socket?") before the next "accept!".
socket? returns the socket descriptor for the socket used for two-way communication in a network object in connected state.
accepting_socket? returns the socket descriptor for the socket accepting connections in a network object after an "establish:" or "auto_establish!" has successfully completed. This socket will be ready for reading (from io_select's point of view) when another process has connected to it and a subsequent "accept!" message will not block.
send: msg_string sends the string, msg_string, to the parser of the partner process. Send will only work after a socket has been established, and a connect has been accept'ed. The msg_string will be parsed in the remote LYMB process, so it must be a valid LYMB message, or sequence of messages, using names of objects that exist in that process.
read! tries to read messages from an already-connected network interface. Any messages that are read are passed to the LYMB parser (parser parse: msg_string). If no messages can be read, returns without doing anything. Reads up to 5 "msg_strings" (the result of 5 "sends" by the partner process) which may contain an arbitrary number of LYMB messages. Any remaining unread msg_strings
will be read on the next call to read!. If the peer has closed the connection, a "read!" message will cause a "close!" message to be sent.
read_sync! same as "read!" but blocks until a message becomes available.
lock! causes all the following messages up until the next unlock! message to be parsed by the remote partner without returning control to the caller of the read! message. Essentially, causes the "read!" to remain blocked until the unlock! is received. This is provided to insure that a transaction, consisting of multiple interdependent steps, is processed as one atomic unit.
unlock! reverses the effect of lock!, and allows the partner process to proceed executing normally.
status? returns the status of the network object (see values above).
status= value sets the status to a new value.
close! Closes the socket returned by "socket?". Changes the status from 2 to either 1 or 0, depending on whether or not "accepting_socket?" returns a valid descriptor accepting connections.
close_accepting! Closes the socket returned by "accepting_socket?". If the status was 1, it becomes 0. If it was 2, the status remains unchanged. The socket returned by "socket?" is not affected.
enable_signals! specify that a SIGIO signal is to be generated when input is available on the socket. Must be in an established or connected state.
disable_signals! disable SIGIO signals for the socket. Must be in an established or connected state.
notify_set[=+-?]
messages can be sent to the class as well as to
instances. They are used by other objects (e.g.
netserver_filter and lymb_process) that want to be
notified when input is available on socket connections they establish.
The first time one of these messages gets sent, it
creates both the collection and an actions object
to be used as the SIGIO signal handler action. The
names chosen for these two objects are such that
they cannot conflict with normal LYMB identifiers.
The signal handler action simply sends a "read!" to
the collection. The signal handler action runs in
immediate mode by default.
auto_read_on!
Registers the socket with the io_select object so
that a "read!" will be sent when input is available.
auto_read_off!
Does the opposite of "auto_read_on!".
--======== network_example1.scr ==========
-- Communicate with a cooperating LYMB process,
-- telling it to display a cube and rotate the cube.
# Establish network port
network new: "net1"
establish: 2098 ;
# Accept connection from remote partner
net1 accept!;
# Tell remote partner to create modeller & actor
net1 send: `
cube_modeller new: "cmod";
actor new: "cube" modeller=cmod rotate_x: 30;
camera new: "c1" position=(5,5,5);
vogle_x11 new: "aren" actors+ cube cameras+ c1 render!;
loop new: "my_loop"
resolution= 1
duration= 5
tick_actions=`
net1 send: "cube rotate_z: 15; aren render!;" ;
';
my_loop start!;
net1 send: "run_loop stop!;" ;
--======== network_example2.scr ==========
-- LYMB Listener:
-- Connect to a remote LYMB process and do whatever it tells me.
# Get hostname
shell new: "sh" command= "hostname" do!;
string new: "hostname" = [sh std_output?] chop!;
# Connect to server via port number
network new: "net2"
connect:( hostname, 2098 );
# Define and execute run_loop
loop new: "run_loop"
resolution= 1
duration= 100000
tick_actions= `
net2 read!;
';
logic new: "status_okay" notequal: ( [net2 status?], -1 )
true: `run_loop start!;'
;
EXAMPLE
The following two LYMB scripts are cooperating processes.
This example is meant to be run in two windows of the same
workstation. Start network_example1.scr in one window
before starting network_example2.scr in a second window.
SEE ALSO
parser(lymb), signal_handler(lymb), socket(2), bind(2),
connect(2), listen(2) netserver_filter(lymb),
lymb_process(lymb)
LIMITATIONS
The number of sockets plus files that a single process can
have open simultaneously is typically around sixty.
Please send comments and suggestions toconsult@rpi.edu