/**
<html>
<title> Distributed TCP/IP Client-Server Networking Example </title>
<body bgcolor=white>

<br>
<br> The <a href="../docs/readme.html#tcpnet"> TCP networking predicates </a>
are primarily intended for <i> internal </i>, i.e. DLP run-time system
use only. The primitives are used in the current DLP run-time system to
implement a high-level distributed communication framework.

However, occasionally it will be useful to implement a dedicated
distributed communication infrastructure.
The following source code example illustrates how TCP predicates
can be used to build <i> special purpose </i> distributed processing
systems in DLP itself.
The program example consists of two objects: <i>pxserver</i> and <i>pxclient</i>.

<a name=pxserver>
<br> <br> Object <i>pxserver</i> is used as a stand-alone program;
once invoked by a "dlp pxserver" command, it will handle multiple
<i> pxclient </i> connections. Each client connection will be processed
by a separate <i>pxserver</i> thread. When client programs
<a href="../docs/readme.html#execution">run in a browser</a>, the
server should run on the same machine from which the client code is
loaded. This is the only way to connect a client to a server without
changing the access policy of a browser. See the Java
<a href="http://java.sun.com/j2se/1.4/docs/tooldocs/tools.html#security">policy tool</a>
documentation. No need to say that you should check the current firewall
settings of the workstations used for a particular distributed processing
problem.

<br><br> Server execution :
<ul>
<li> invocation of a <i>pxserver</i> object as a stand-alone program
     results in the exectution of method <i>main</i>.
<li> method <i>main</i> creates a server socket handle <i>ServerSocket</i>
     by means of the library built-in <i>tcp_server</i> and creates a new
     active <i>pxserver</i> object. A <i>ServerSocket</i> is
     unique for a particular port / machine combination.
<li> an active <i>pxserver</i> object invokes <i>tcp_accept</i> : the
     current active <i>pxserver</i> thread will block until a client
     invokes a <i>tcp_client</i> method.
<li> after accepting a connection, a <i>ServerStreamIn</i> and <i>ServerStreamOut</i>
     is returned as well as the <i>ClientHostName</i> of the client.
     The <i>ServerStreamIn</i> is connected to a <i>ClientStreamOut</i>
     and a <i>ServerStreamOut</i> is connected to a <i>ClientStreamIn</i>.
<li> the server starts a new active <i>pxserver</i> thread that will
     handle the next client connection after which it starts its own
     server loop :
<li> the server loop reads an arbitrary term from <i>ServerStreamIn</i>
     by means of <i>tcp_get_term</i> and processes the received information.
<li> an answer is sent back to the client : <i>tcp_put_term</i> writes a
     <i>ServerReply</i> term to <i>ServerStreamOut</i>.
</ul>

<pre>
**/


:-object pxserver.

	var port = 4321.

	main :-
		tcp_server(port, ServerSocket),
		format('Server ~w : socket = ~w~n', [this, ServerSocket]),
		new(pxserver(ServerSocket), _),
		format('end of ~w main~n', [this]).

	pxserver(ServerSocket) :-
		server_init(ServerSocket, ServerStreamIn, ServerStreamOut),
		server_loop(ServerStreamIn, ServerStreamOut).

	server_init(ServerSocket, ServerStreamIn, ServerStreamOut) :-
		tcp_accept(ServerSocket, ServerStreamIn, ServerStreamOut, ClientHostName),
		format('Server ~w : accepting new client connection from ~w~n',
			[this, ClientHostName]),
		new(pxserver(ServerSocket), _).

	server_loop(ServerStreamIn, ServerStreamOut) :-
		repeat,
			tcp_get_term(ServerStreamIn, ClientRequest),
			process_mesg(ClientRequest, ServerReply),
			tcp_put_term(ServerStreamOut, ServerReply),
		ServerReply = thread_shutdown,
		!,
		tcp_close(ServerStreamIn),
		tcp_close(ServerStreamOut).

	process_mesg(Input, Reply) :-
		format('Server ~w : tcp get = ~w~n', [this, Input]),
		message_type(Input, Reply),
		format('Server ~w : tcp put = ~w~n', [this, Reply]).

	message_type(mul_int(I0,I1), ReplyTerm) :-
		integer(I0),
		integer(I1),
		!,
		IR is I0 * I1,
		ReplyTerm = mul_val(IR).
	message_type(InputTerm, ReplyTerm) :-
		InputTerm = [client, [_]],
		!,
		ReplyTerm = [server, [ServerHost]],
		local_host(ServerHost, _).
	message_type(client_shutdown, thread_shutdown) :- !,
		format('~nServer Thread ~w shutdown~n~n', [this]).
	message_type(shutdown, thread_shutdown) :-
		!.
	message_type(Input, Reply) :-
		Reply = unknown_message_type(Input).

:-end_object pxserver.


/**
</pre>

<a name=pxclient>
A <i>pxclient</i> object can execute as a stand-alone client or
can execute in a browser.
Typically, several active <i> pxclient </i> objects will connect
to a single multi-threaded <i> pxserver </i> object simultaneously.
In case one or more <i>pxclient</i> objects are running in a browser
on different machines, the <i>pxserver</i> should run on the same
machine from which the <i>pxclient</i> code is loaded.

<pre>
**/


:-object pxclient.

	var port = 4321, loop = 5 .

	main :-
		text_area(BrowserTextArea),
		set_output(BrowserTextArea),
		code_base_host(ServerHost),
		pxclient(ServerHost, port),
		format('end of ~w main~n', [this]).

	pxclient(ServerHost, ServerPort) :-
		format('Code base host = ~w~n', [ServerHost]),
		tcp_client(ServerHost, ServerPort, 10, StreamIn, StreamOut),
		format('client socket = ~w, ~w~n', [StreamIn,StreamOut]),

		client_init(StreamIn, StreamOut),
		client_loop(StreamIn, StreamOut),
		client_exit(StreamIn, StreamOut),

		tcp_close(StreamIn),
		tcp_close(StreamOut).

	client_init(StreamIn, StreamOut) :-
		local_host(ClientHost, _),
		%% ClientHost = localhost,
		format('Client host = ~w~n', [ClientHost]),
		tcp_put_term(StreamOut, [client, [ClientHost]]),
		tcp_get_term(StreamIn, OK),
		format('server answer = ~w~n', [OK]).

	client_loop(StreamIn, StreamOut) :-
		repeat,
			ServerInput = mul_int(loop, 100),
			format('Client ~w : tcp put = ~w~n', [this, ServerInput]),
			tcp_put_term(StreamOut, ServerInput),
			tcp_get_term(StreamIn,  ServerReply),
			format('Client ~w : tcp get = ~w~n', [this, ServerReply]),
			-- loop,
		loop =:= 0,
		!.

	client_exit(StreamIn, StreamOut) :-
		tcp_put_term(StreamOut, client_shutdown),
		tcp_get_term(StreamIn, thread_shutdown).

:-end_object pxclient.


/**
</pre>
<a name=pxsock>

Another (somewhat unusual) example of running the client - server objects
is shown below. When the object <i> pxsock </i> is executed by means of a
"dlp pxsock" command, it will create an active <a href=#pxserver>
pxserver </a> as well as several active <a href=#pxclient> pxclient </a>
threads. These active threads will communicate within the context of a
single program by means of the established socket connections.

<pre>
**/


:-object pxsock.

	var port = 4321.

	main :-
		tcp_server(port, Socket),
		local_host(Host, _),
		new(pxserver(Socket), _),	%% server thread
		new(pxclient(Host,port), _),	%% client thread 1
		new(pxclient(Host,port), _),	%% client thread 2
		new(pxclient(Host,port), _),	%% client thread 3
		format('end of ~w main~n', [this]).

:-end_object pxsock.

/**
</pre>
</body>
</html>
**/
