COGENT Version 2.3 Help

Socket / Server


The Socket/Server box (only available in the registered version of COGENT) is the server half of a TCP/IP interface for COGENT. (See Socket/Client for the client half of the TCP/IP interface.) The interface allows multiple models to be run simultaneously (but asynchronously) on the same or different machines, communicating with each other via Socket boxes, and it allows COGENT models to interact with networked resources (such as web servers and Telnet clients).

A Socket/Server box listens on a port (whose number is specified by a property of the box) for client connection requests. It starts listening when the box is initialised, and checks for new connections every cycle; it accepts all incoming connection requests, setting up an open connection for each. This continues until the box is stopped or reinitialised, when it is shutdown and all current connections are closed. Reinitialisation, of course, implies that the box starts listening again immediately afterwards.

Other than special triggers, all messages sent to a Socket/Server box along a send arrow will be transmitted along all open connections from that box. Similarly, any messages incoming through open connections will be transmitted along all send arrows leading from the Socket/Server box.

Execution and termination

A model containing one or more Socket/Server boxes will continue running if any connections from or to a box in the model are still open, or if a server box is listening for connections.

Sending a Socket/Server box a close message will close all open connections from or to that box, but it will not shut down the server, if one is running. Sending the box a stop message will close all open connections to or from the box, like the close message, and moreover, it will shut down server in that box. This allows the usual default conditions to govern whether the whole model halts naturally or continues running.

It should be noted that unlike COGENT models in general, model runs using Socket boxes (servers or client) cannot be halted and restarted in a later OOS session. This is because ending the OOS session will close any open connections, so clients will not still be connected when the model is restarted. Initialisation is usually required.

Data formats

Socket boxes support two data formats to transmit and receive data: raw mode sends and receives lists of ASCII values, corresponding to lines of textual output and input, whereas the default mode sends and receives prolog terms. Raw mode is useful to allow COGENT models to interact with arbitrary networked systems, such as web servers, or with Telnet clients for user interaction. The default mode, by contrast, simply sends and receives prolog terms. This is more appropriate for direct communication between COGENT models.

Raw mode: If the box is configured to use raw mode, messages corresponding to lines of output must be specified as raw(LineString) where LineString is a prolog string, or a list of ASCII values, for example raw("hello") or equivalently raw([104, 101, 108, 108, 111]). These strings are each formatted on the output stream with a following newline (ASCII 10).

Similarly, lines of input from connections, terminated with newlines, are converted to raw(LineString) format before being passed along send arrows to other boxes. The newline character is not included in the parsed string, and any carriage returns (ASCII 13) in the input are ignored.

Default mode: In the default mode, any prolog term sent to a Socket box (except special triggers) will be sent on along any open connections to the peers, which must also be in default mode to ensure success.

Tagging and individual connections

So far, we have assumed that all outgoing messages will be sent to all open connections, and incoming messages could come from any connection, without identification. But a single Socket/Server may be connected to any number of clients, and similarly a single client may be connected to any number of Socket/Server boxes. Obviously there may be cases when we wish to send different messages to different connections, and when we want to identify the source of an incoming message. Both require a method for identifying individual open connections uniquely.

The problem of unique reference can be addressed by creating a system of identifiers. We have chosen to implement this as the state of the box, by analogy with the state of a buffer. In the present case, the state of the box comprises a list of unique identifiers for each currently open connection. It is maintained by the system, so it is not possible to directly add or delete elements to or from the state. Each element has the form socket(Host, UniqueID) where Host gives the hostname and port number, or a numeric IP address, and UniqueID is an integer generated by the system. It is possible to use the standard match procedure to read elements from the state.

Sending messages to individual connections can be achieved by simply attaching this identifier to the message to be sent. For example, if Socket=socket('localhost':15000, 8), then we can send a raw-mode message to this connection alone by using the form raw(Socket, LineString). For default mode, we have introduced a special term message/2, which is used in an analogous way: message(Socket, PrologTerm).

Attaching Socket identifiers to incoming messages happens analogously. It is necessary to specify that the box should tag incoming messages using a special property Tag Messages. If this is checked, all incoming messages will be in the form raw(Socket, LineString) or message(Socket, PrologTerm) instead of the default forms.

A final refinement of this tagging mechanism allows the setting of aliases for socket identifiers. If a connection has an alias, it can be specified instead of a socket/2 term on outgoing messages, and it will be used instead of a socket/2 term on tagged incoming messages, and when matching against the contents of the state. Aliases can be set in a variety of ways: first, an alternative form of the open message has a second argument that specifies the alias to be used for the connection, for example open(localhost:15000, myalias). Secondly, for an already-existing connection, it can be given an alias using a special message alias(Socket, Alias). Finally, a remote peer can specify its own alias, using a special message call_me(Alias). Setting an alias for a connection overrides any previous aliases for that connection.


Port (positive integer)
This specifies the port number on which the server listens.
Raw IO (boolean)
This is used to specify whether information is transmitted and received as lists of ASCII values (when enabled), or as prolog terms (when disabled). This will affect all connections to or from the box.
Tag Messages (boolean)
This is used to specify whether incoming messages should be tagged with a socket identifier or alias. In raw mode the resulting message will be of the form raw(Socket, LineString) whereas in default mode it will be of the form message(Socket, PrologTerm). If this property is unchecked, incoming messages will not be tagged.

Special triggers

If a Socket/Server box receives a close message, all open connections to or from that box will be closed, and the model may be able to stop executing. The box itself is not stopped, however, and this will not shutdown an active server. If an argument is specified, it must be a socket identifier or alias, and only the specified connection will be closed.
Like the stop message generally, it causes the recipient box to cease all operations until the box is next initialised. In the case of Socket/Server boxes, there are two extra side effects: first, all open connections with other boxes, whether clients or servers, are closed (as for the close trigger); second, and crucially, the server in the box that receives the stop message is also shut down.
raw(Socket, LineString)
If the box is configured for Raw IO any messages sent to it must be in this format, and the LineString will be written to the outgoing stream. In Raw IO mode, all incoming data is also parsed into lines, and passed along send arrows as raw(LineString) terms. This allows the box to interface with arbitrary network processes, such as web servers. If two arguments are specified, the first must be a Socket identifier or alias, and the message will only be sent to the connection that is specified. When Tag Messages is checked, incoming messages will be passed along arrows to other boxes in this form.
message(Socket, PrologTerm)
The binary form (message/2) form is used to send a Prolog term to a specified connection, and the unary form (message/1) just passes the term to any connections without interpreting it. In the binary form, Socket may be either a socket identifier or an alias. When Tag Messages is checked, incoming messages will be passed along arrows to other boxes in the binary form. The unary form is used to 'escape' a message, that is, to pass it on uninterpreted to any connections. The unary form is also interpreted at the peer end of a connection, so any peer-end messages (e.g. call_me/1) can be escaped too.
alias(Socket, Alias)
This message is used to specify an alias for a connection. The first argument must be a socket identifier or previous alias, and the second will become the new alias.
This message is unusual in that it is not interpreted by the local target box, but by the box at the other end of the connection. For want of a better term, I call these peer-end messages. call_me/1 allows a peer to specify its own alias. You may also want to use the form message(Socket, call_me(Alias)) to send a call_me/1 to a specific connection.

Known bugs

Windows 9x client mode
The client side on MS windows 95 and 98 gets stuck when attempting to make a connection. This only happens the first time a connection is attempted during an oos session, and it can be unstuck by either typing into the oos console (if enabled), or by selecting "End task" for the oos process in the Task manager window (Accessible by CTRL-ALT-DEL on a windows 95/98 machine). This will attempt to kill the oos process, but will not succeed, and a side effect is to unstick the connection. After a few moments a dialog box will appear, saying the program is not responding: make sure you click Cancel here. The bug seems to be due to an incompatibility between SWI prolog and the windows 95/98 winsock.dll; it does not affect the UNIX version, and may well not affect NT-derived windows platforms.
Raw mode and binary data
Raw mode should be adequate for text data, but it will mangle incoming binary data, since it currently ignores CR characters and splits the stream into lines terminated by LF characters. This could presumably be fixed somehow, if anybody cares.


We would like to thank David Glasspool and John Fox for their generous support, which allowed Peter Yule ( to develop this box.

COGENT Version 2.3 Help