Distributed programming: Difference between revisions
Content added Content deleted
m (→{{header|Phix}}: marked p2js incompatible) |
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
||
Line 16: | Line 16: | ||
server.ads: |
server.ads: |
||
< |
<syntaxhighlight lang="ada">package Server is |
||
pragma Remote_Call_Interface; |
pragma Remote_Call_Interface; |
||
procedure Foo; |
procedure Foo; |
||
function Bar return Natural; |
function Bar return Natural; |
||
end Server;</ |
end Server;</syntaxhighlight> |
||
server.adb: |
server.adb: |
||
< |
<syntaxhighlight lang="ada">package body Server is |
||
Count : Natural := 0; |
Count : Natural := 0; |
||
Line 35: | Line 35: | ||
return Count; |
return Count; |
||
end Bar; |
end Bar; |
||
end Server;</ |
end Server;</syntaxhighlight> |
||
client.adb: |
client.adb: |
||
< |
<syntaxhighlight lang="ada">with Server; |
||
with Ada.Text_IO; |
with Ada.Text_IO; |
||
Line 46: | Line 46: | ||
Server.Foo; |
Server.Foo; |
||
Ada.Text_IO.Put_Line ("Calling Bar: " & Integer'Image (Server.Bar)); |
Ada.Text_IO.Put_Line ("Calling Bar: " & Integer'Image (Server.Bar)); |
||
end Client;</ |
end Client;</syntaxhighlight> |
||
required config (dsa.cfg): |
required config (dsa.cfg): |
||
< |
<syntaxhighlight lang="ada">configuration DSA is |
||
pragma Starter (None); |
pragma Starter (None); |
||
Line 61: | Line 61: | ||
procedure Client; |
procedure Client; |
||
for Client_Partition'Main use Client; |
for Client_Partition'Main use Client; |
||
end DSA;</ |
end DSA;</syntaxhighlight> |
||
compilation: |
compilation: |
||
Line 120: | Line 120: | ||
Using PVM [http://www.csm.ornl.gov/pvm/pvm_home.html] |
Using PVM [http://www.csm.ornl.gov/pvm/pvm_home.html] |
||
This program is in a sense both a server and a client, depending on if its task is spawned with a command-line argument: if yes, it spawns another task of the same executible on the parallel virtual machine and waits for it to transmit data; if no, it transmits data and is done. |
This program is in a sense both a server and a client, depending on if its task is spawned with a command-line argument: if yes, it spawns another task of the same executible on the parallel virtual machine and waits for it to transmit data; if no, it transmits data and is done. |
||
< |
<syntaxhighlight lang="c">#include <stdio.h> |
||
#include <stdlib.h> |
#include <stdlib.h> |
||
#include <pvm3.h> |
#include <pvm3.h> |
||
Line 169: | Line 169: | ||
pvm_exit(); |
pvm_exit(); |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight>{{out}}(running it on PVM console, exe is /tmp/a.out)<syntaxhighlight lang="text">pvm> spawn -> /tmp/a.out 1 |
||
spawn -> /tmp/a.out 1 |
spawn -> /tmp/a.out 1 |
||
[2] |
[2] |
||
Line 179: | Line 179: | ||
[2:t40028] got msg type 1: 1804289383 0.394383 |
[2:t40028] got msg type 1: 1804289383 0.394383 |
||
[2:t40028] EOF |
[2:t40028] EOF |
||
[2] finished</ |
[2] finished</syntaxhighlight> |
||
=={{header|C sharp|C#}}== |
=={{header|C sharp|C#}}== |
||
Start the program with "server" parameter to start the server, and "client" to start the client. The client will send data to the server and receive a response. The server will wait for data, display the data received, and send a response. |
Start the program with "server" parameter to start the server, and "client" to start the client. The client will send data to the server and receive a response. The server will wait for data, display the data received, and send a response. |
||
< |
<syntaxhighlight lang="csharp"> |
||
using System; |
using System; |
||
using System.IO; |
using System.IO; |
||
Line 282: | Line 282: | ||
public string Loot = "140 tonnes of jade"; |
public string Loot = "140 tonnes of jade"; |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|D}}== |
=={{header|D}}== |
||
Line 289: | Line 289: | ||
This library is not standard, so this code (by Adam D. Ruppe) could and should be rewritten using more standard means. |
This library is not standard, so this code (by Adam D. Ruppe) could and should be rewritten using more standard means. |
||
< |
<syntaxhighlight lang="d">import arsd.rpc; |
||
struct S1 { |
struct S1 { |
||
Line 355: | Line 355: | ||
server.eventLoop; |
server.eventLoop; |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|E}}== |
=={{header|E}}== |
||
Line 366: | Line 366: | ||
(The protocol is symmetric; this program is the server only in that it is the one which is started first and exports an object.) |
(The protocol is symmetric; this program is the server only in that it is the one which is started first and exports an object.) |
||
< |
<syntaxhighlight lang="e">def storage := [].diverge() |
||
def logService { |
def logService { |
||
Line 384: | Line 384: | ||
def sturdyRef := makeSturdyRef.temp(logService) |
def sturdyRef := makeSturdyRef.temp(logService) |
||
println(<captp>.sturdyToURI(sturdyRef)) |
println(<captp>.sturdyToURI(sturdyRef)) |
||
interp.blockAtTop()</ |
interp.blockAtTop()</syntaxhighlight> |
||
This will print the URL of the service and run it until aborted. |
This will print the URL of the service and run it until aborted. |
||
Line 392: | Line 392: | ||
The URL provided by the server is given as the argument to this program. |
The URL provided by the server is given as the argument to this program. |
||
< |
<syntaxhighlight lang="e">def [uri] := interp.getArgs() |
||
introducer.onTheAir() |
introducer.onTheAir() |
||
def sturdyRef := <captp>.sturdyFromURI(uri) |
def sturdyRef := <captp>.sturdyFromURI(uri) |
||
Line 405: | Line 405: | ||
println(`At $time: $line`) |
println(`At $time: $line`) |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Erlang}}== |
=={{header|Erlang}}== |
||
Line 412: | Line 412: | ||
srv.erl |
srv.erl |
||
< |
<syntaxhighlight lang="erlang">-module(srv). |
||
-export([start/0, wait/0]). |
-export([start/0, wait/0]). |
||
Line 430: | Line 430: | ||
wait(); |
wait(); |
||
Any -> io:fwrite("Error ~p~n", [Any]) |
Any -> io:fwrite("Error ~p~n", [Any]) |
||
end.</ |
end.</syntaxhighlight> |
||
=== Client === |
=== Client === |
||
client.erl |
client.erl |
||
< |
<syntaxhighlight lang="erlang">-module(client). |
||
-export([start/0, wait/0]). |
-export([start/0, wait/0]). |
||
Line 451: | Line 451: | ||
{hello, Any} -> io:fwrite("Received ~p~n", [Any]); |
{hello, Any} -> io:fwrite("Received ~p~n", [Any]); |
||
Any -> io:fwrite("Error ~p~n", [Any]) |
Any -> io:fwrite("Error ~p~n", [Any]) |
||
end.</ |
end.</syntaxhighlight> |
||
running it (*comes later) |
running it (*comes later) |
||
Line 474: | Line 474: | ||
===Server=== |
===Server=== |
||
< |
<syntaxhighlight lang="factor">USING: concurrency.distributed concurrency.messaging threads io.sockets io.servers ; |
||
QUALIFIED: concurrency.messaging |
QUALIFIED: concurrency.messaging |
||
: prettyprint-message ( -- ) concurrency.messaging:receive . flush prettyprint-message ; |
: prettyprint-message ( -- ) concurrency.messaging:receive . flush prettyprint-message ; |
||
[ prettyprint-message ] "logger" spawn dup name>> register-remote-thread |
[ prettyprint-message ] "logger" spawn dup name>> register-remote-thread |
||
"127.0.0.1" 9000 <inet4> <node-server> start-server</ |
"127.0.0.1" 9000 <inet4> <node-server> start-server</syntaxhighlight> |
||
Note: we are using QUALIFIED: with the concurrency.messaging vocabulary because the "receive" word is defined in io.sockets vocabulary too. If someone have a cleaner way to handle this. |
Note: we are using QUALIFIED: with the concurrency.messaging vocabulary because the "receive" word is defined in io.sockets vocabulary too. If someone have a cleaner way to handle this. |
||
===Client=== |
===Client=== |
||
< |
<syntaxhighlight lang="factor">USING: concurrency.distributed io.sockets ; |
||
QUALIFIED: concurrency.messaging |
QUALIFIED: concurrency.messaging |
||
{ "Hello Remote Factor!" H{ { "key1" "value1" } } } |
{ "Hello Remote Factor!" H{ { "key1" "value1" } } } |
||
"127.0.0.1" 9000 <inet4> "logger" <remote-thread> concurrency.messaging:send</ |
"127.0.0.1" 9000 <inet4> "logger" <remote-thread> concurrency.messaging:send</syntaxhighlight> |
||
How to Run: |
How to Run: |
||
Line 501: | Line 501: | ||
'''Server:''' |
'''Server:''' |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 530: | Line 530: | ||
} |
} |
||
http.Serve(listener, nil) |
http.Serve(listener, nil) |
||
}</ |
}</syntaxhighlight> |
||
'''Client:''' |
'''Client:''' |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 554: | Line 554: | ||
} |
} |
||
fmt.Printf("Tax on %.2f: %.2f\n", amount, tax) |
fmt.Printf("Tax on %.2f: %.2f\n", amount, tax) |
||
}</ |
}</syntaxhighlight> |
||
{{out | Client output}} |
{{out | Client output}} |
||
<pre> |
<pre> |
||
Line 565: | Line 565: | ||
'''.proto:''' |
'''.proto:''' |
||
< |
<syntaxhighlight lang="proto">syntax = "proto3"; |
||
service TaxComputer { |
service TaxComputer { |
||
Line 573: | Line 573: | ||
message Amount { |
message Amount { |
||
int32 cents = 1; |
int32 cents = 1; |
||
}</ |
}</syntaxhighlight> |
||
'''Server:''' |
'''Server:''' |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 608: | Line 608: | ||
taxcomputer.RegisterTaxComputerServer(grpcServer, &taxServer{.05}) |
taxcomputer.RegisterTaxComputerServer(grpcServer, &taxServer{.05}) |
||
grpcServer.Serve(listener) |
grpcServer.Serve(listener) |
||
}</ |
}</syntaxhighlight> |
||
'''Client:''' |
'''Client:''' |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 635: | Line 635: | ||
} |
} |
||
fmt.Println("Tax on", amt.Cents, "cents is", tax.Cents, "cents") |
fmt.Println("Tax on", amt.Cents, "cents is", tax.Cents, "cents") |
||
}</ |
}</syntaxhighlight> |
||
{{out | Client output}} |
{{out | Client output}} |
||
<pre> |
<pre> |
||
Line 647: | Line 647: | ||
Like gRPC, Thrift requires a language independent interface definition file: |
Like gRPC, Thrift requires a language independent interface definition file: |
||
< |
<syntaxhighlight lang="thrift">service TaxService { |
||
i32 tax(1: i32 amt) |
i32 tax(1: i32 amt) |
||
}</ |
}</syntaxhighlight> |
||
'''Server:''' |
'''Server:''' |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 683: | Line 683: | ||
log.Fatal(err) |
log.Fatal(err) |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
'''Client:''' |
'''Client:''' |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 714: | Line 714: | ||
} |
} |
||
transport.Close() |
transport.Close() |
||
}</ |
}</syntaxhighlight> |
||
{{out | Client output}} |
{{out | Client output}} |
||
<pre> |
<pre> |
||
Line 735: | Line 735: | ||
===Server=== |
===Server=== |
||
< |
<syntaxhighlight lang="javascript">var net = require('net') |
||
var server = net.createServer(function (c){ |
var server = net.createServer(function (c){ |
||
Line 743: | Line 743: | ||
server.listen(3000, 'localhost') |
server.listen(3000, 'localhost') |
||
</syntaxhighlight> |
|||
</lang> |
|||
===Client=== |
===Client=== |
||
< |
<syntaxhighlight lang="javascript">var net = require('net') |
||
conn = net.createConnection(3000, '192.168.1.x') |
conn = net.createConnection(3000, '192.168.1.x') |
||
Line 757: | Line 757: | ||
conn.on('data', function(msg){ |
conn.on('data', function(msg){ |
||
console.log(msg.toString()) |
console.log(msg.toString()) |
||
})</ |
})</syntaxhighlight> |
||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
Line 763: | Line 763: | ||
If a group of CPUs, including multiple cores on a single machine or a cluster running with paswordless ssh login, is used, |
If a group of CPUs, including multiple cores on a single machine or a cluster running with paswordless ssh login, is used, |
||
the following can be set up as an example: |
the following can be set up as an example: |
||
< |
<syntaxhighlight lang="julia"># From Julia 1.0's online docs. File countheads.jl available to all machines: |
||
function count_heads(n) |
function count_heads(n) |
||
Line 771: | Line 771: | ||
end |
end |
||
c |
c |
||
end</ |
end</syntaxhighlight> |
||
We then run the following on the primary client: |
We then run the following on the primary client: |
||
< |
<syntaxhighlight lang="julia"> |
||
using Distributed |
using Distributed |
||
@everywhere include_string(Main, $(read("count_heads.jl", String)), "count_heads.jl") |
@everywhere include_string(Main, $(read("count_heads.jl", String)), "count_heads.jl") |
||
Line 781: | Line 781: | ||
println(fetch(a)+fetch(b)) # total heads of 200 million coin flips, half on each CPU |
println(fetch(a)+fetch(b)) # total heads of 200 million coin flips, half on each CPU |
||
</ |
</syntaxhighlight> {{output}} <pre> |
||
100001564 |
100001564 |
||
</pre> |
</pre> |
||
Line 795: | Line 795: | ||
In one terminal window, start up the REPL |
In one terminal window, start up the REPL |
||
< |
<syntaxhighlight lang="bash"> |
||
$ ./bin/lfe |
$ ./bin/lfe |
||
Erlang/OTP 17 [erts-6.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] |
Erlang/OTP 17 [erts-6.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] |
||
Line 801: | Line 801: | ||
LFE Shell V6.2 (abort with ^G) |
LFE Shell V6.2 (abort with ^G) |
||
> |
> |
||
</syntaxhighlight> |
|||
</lang> |
|||
And then enter the following code |
And then enter the following code |
||
< |
<syntaxhighlight lang="lisp"> |
||
> (defun get-server-name () |
> (defun get-server-name () |
||
(list_to_atom (++ "exampleserver@" (element 2 (inet:gethostname))))) |
(list_to_atom (++ "exampleserver@" (element 2 (inet:gethostname))))) |
||
Line 825: | Line 825: | ||
(x |
(x |
||
(io:format "Unexpected pattern: ~p~n" `(,x))))) |
(io:format "Unexpected pattern: ~p~n" `(,x))))) |
||
</syntaxhighlight> |
|||
</lang> |
|||
===Client=== |
===Client=== |
||
Line 831: | Line 831: | ||
In another terminal window, start up another LFE REPL and ender the following code: |
In another terminal window, start up another LFE REPL and ender the following code: |
||
< |
<syntaxhighlight lang="lisp"> |
||
> (defun get-server-name () |
> (defun get-server-name () |
||
(list_to_atom (++ "exampleserver@" (element 2 (inet:gethostname))))) |
(list_to_atom (++ "exampleserver@" (element 2 (inet:gethostname))))) |
||
Line 846: | Line 846: | ||
(io:format "Unexpected pattern: ~p~n" (list x)))) |
(io:format "Unexpected pattern: ~p~n" (list x)))) |
||
'ok) |
'ok) |
||
</syntaxhighlight> |
|||
</lang> |
|||
To use this code, simply start the server in the server terminal: |
To use this code, simply start the server in the server terminal: |
||
< |
<syntaxhighlight lang="lisp"> |
||
> (start) |
> (start) |
||
exampleserver@yourhostname ready |
exampleserver@yourhostname ready |
||
ok |
ok |
||
(exampleserver@yourhostname)> |
(exampleserver@yourhostname)> |
||
</syntaxhighlight> |
|||
</lang> |
|||
Send some messages from the client terminal: |
Send some messages from the client terminal: |
||
< |
<syntaxhighlight lang="lisp"> |
||
> (send "hi there") |
> (send "hi there") |
||
connecting to exampleserver@yourhostname |
connecting to exampleserver@yourhostname |
||
Line 873: | Line 873: | ||
ok |
ok |
||
(exampleclient@yourhostname)> |
(exampleclient@yourhostname)> |
||
</syntaxhighlight> |
|||
</lang> |
|||
And check out the results back in the server terminal window: |
And check out the results back in the server terminal window: |
||
< |
<syntaxhighlight lang="lisp"> |
||
Got "hi there" from exampleclient@yourhostname |
Got "hi there" from exampleclient@yourhostname |
||
Got 42 from exampleclient@yourhostname |
Got 42 from exampleclient@yourhostname |
||
Got {key,value} from exampleclient@yourhostname |
Got {key,value} from exampleclient@yourhostname |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
=={{header|Mathematica}} / {{header|Wolfram Language}}== |
||
The following sends a request for a random number to be generated on each of two nodes, these are then transmitted back to be assembled into an array with two elements. Omitting the first line, will cause the program to be run on all configured remote computers. |
The following sends a request for a random number to be generated on each of two nodes, these are then transmitted back to be assembled into an array with two elements. Omitting the first line, will cause the program to be run on all configured remote computers. |
||
< |
<syntaxhighlight lang="mathematica">LaunchKernels[2]; |
||
ParallelEvaluate[RandomReal[]] |
ParallelEvaluate[RandomReal[]] |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Nim}}== |
=={{header|Nim}}== |
||
{{libheader|nanomsg}} |
{{libheader|nanomsg}} |
||
< |
<syntaxhighlight lang="nim">import os, nanomsg |
||
proc sendMsg(s: cint, msg: string) = |
proc sendMsg(s: cint, msg: string) = |
||
Line 932: | Line 932: | ||
node0 paramStr(2) |
node0 paramStr(2) |
||
elif paramStr(1) == "node1": |
elif paramStr(1) == "node1": |
||
node1 paramStr(2)</ |
node1 paramStr(2)</syntaxhighlight> |
||
Usage: |
Usage: |
||
<pre>./pair node0 tcp://127.0.0.1:25000 |
<pre>./pair node0 tcp://127.0.0.1:25000 |
||
Line 945: | Line 945: | ||
<tt>ActionObjectProtocol.h</tt> |
<tt>ActionObjectProtocol.h</tt> |
||
< |
<syntaxhighlight lang="objc">#import <Foundation/Foundation.h> |
||
// our protocol allows "sending" "strings", but we can implement |
// our protocol allows "sending" "strings", but we can implement |
||
// everything we could for a "local" object |
// everything we could for a "local" object |
||
@protocol ActionObjectProtocol |
@protocol ActionObjectProtocol |
||
- (NSString *)sendMessage: (NSString *)msg; |
- (NSString *)sendMessage: (NSString *)msg; |
||
@end</ |
@end</syntaxhighlight> |
||
<tt>ActionObject.h</tt> |
<tt>ActionObject.h</tt> |
||
< |
<syntaxhighlight lang="objc">#import <Foundation/Foundation.h> |
||
#import "ActionObjectProtocol.h" |
#import "ActionObjectProtocol.h" |
||
@interface ActionObject : NSObject <ActionObjectProtocol> |
@interface ActionObject : NSObject <ActionObjectProtocol> |
||
// we do not have much for this example! |
// we do not have much for this example! |
||
@end</ |
@end</syntaxhighlight> |
||
<tt>ActionObject.m</tt> |
<tt>ActionObject.m</tt> |
||
< |
<syntaxhighlight lang="objc">#import <Foundation/Foundation.h> |
||
#import "ActionObject.h" |
#import "ActionObject.h" |
||
Line 970: | Line 970: | ||
return @"server answers ..."; |
return @"server answers ..."; |
||
} |
} |
||
@end</ |
@end</syntaxhighlight> |
||
<tt>server.m</tt> |
<tt>server.m</tt> |
||
< |
<syntaxhighlight lang="objc">#import <Foundation/Foundation.h> |
||
#import "ActionObject.h" |
#import "ActionObject.h" |
||
Line 1,007: | Line 1,007: | ||
} |
} |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
===Client=== |
===Client=== |
||
<tt>client.m</tt> |
<tt>client.m</tt> |
||
< |
<syntaxhighlight lang="objc">#import <Foundation/Foundation.h> |
||
#import "ActionObjectProtocol.h" |
#import "ActionObjectProtocol.h" |
||
Line 1,048: | Line 1,048: | ||
} |
} |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
=={{header|OCaml}}== |
=={{header|OCaml}}== |
||
Line 1,056: | Line 1,056: | ||
=== Server === |
=== Server === |
||
< |
<syntaxhighlight lang="ocaml">open Printf |
||
let create_logger () = |
let create_logger () = |
||
Line 1,078: | Line 1,078: | ||
register "search" search; |
register "search" search; |
||
Join.Site.listen (Unix.ADDR_INET (Join.Site.get_local_addr(), 12345)); |
Join.Site.listen (Unix.ADDR_INET (Join.Site.get_local_addr(), 12345)); |
||
wait ()</ |
wait ()</syntaxhighlight> |
||
=== Client === |
=== Client === |
||
< |
<syntaxhighlight lang="ocaml">open Printf |
||
let ns_there = Join.Ns.there (Unix.ADDR_INET (Join.Site.get_local_addr(), 12345)) |
let ns_there = Join.Ns.there (Unix.ADDR_INET (Join.Site.get_local_addr(), 12345)) |
||
Line 1,102: | Line 1,102: | ||
log "foo"; |
log "foo"; |
||
log "shoe"; |
log "shoe"; |
||
find "foo"</ |
find "foo"</syntaxhighlight> |
||
=={{header|Oz}}== |
=={{header|Oz}}== |
||
We show a program that starts a server on a remote machine, exchanges two messages with that server and finally shuts it down. |
We show a program that starts a server on a remote machine, exchanges two messages with that server and finally shuts it down. |
||
< |
<syntaxhighlight lang="oz">declare |
||
functor ServerCode |
functor ServerCode |
||
export |
export |
||
Line 1,146: | Line 1,146: | ||
%% shut down server |
%% shut down server |
||
{RM close}</ |
{RM close}</syntaxhighlight> |
||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
Using Data::Dumper and Safe to transmit arbitrary data structures as serialized text between hosts. Same code works as both sender and receiver. |
Using Data::Dumper and Safe to transmit arbitrary data structures as serialized text between hosts. Same code works as both sender and receiver. |
||
< |
<syntaxhighlight lang="perl">use Data::Dumper; |
||
use IO::Socket::INET; |
use IO::Socket::INET; |
||
use Safe; |
use Safe; |
||
Line 1,192: | Line 1,192: | ||
} else { |
} else { |
||
send_data('some_host', { a=>100, b=>[1 .. 10] }); |
send_data('some_host', { a=>100, b=>[1 .. 10] }); |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Line 1,198: | Line 1,198: | ||
There is also a server/client/broker example. |
There is also a server/client/broker example. |
||
Obviously you can trivially serialize() and deserialize() any Phix data to and from a string. |
Obviously you can trivially serialize() and deserialize() any Phix data to and from a string. |
||
<!--< |
<!--<syntaxhighlight lang="phix">(notonline)--> |
||
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (zmq dll/so)</span> |
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (zmq dll/so)</span> |
||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"durapub:\n"</span><span style="color: #0000FF;">)</span> |
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"durapub:\n"</span><span style="color: #0000FF;">)</span> |
||
Line 1,227: | Line 1,227: | ||
<span style="color: #000000;">zmq_close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">publisher</span><span style="color: #0000FF;">)</span> |
<span style="color: #000000;">zmq_close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">publisher</span><span style="color: #0000FF;">)</span> |
||
<span style="color: #000000;">zmq_term</span><span style="color: #0000FF;">(</span><span style="color: #000000;">context</span><span style="color: #0000FF;">)</span> |
<span style="color: #000000;">zmq_term</span><span style="color: #0000FF;">(</span><span style="color: #000000;">context</span><span style="color: #0000FF;">)</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
<!--< |
<!--<syntaxhighlight lang="phix">(notonline)--> |
||
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (zmq dll/so)</span> |
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (zmq dll/so)</span> |
||
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"durasub:\n"</span><span style="color: #0000FF;">)</span> |
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"durasub:\n"</span><span style="color: #0000FF;">)</span> |
||
Line 1,260: | Line 1,260: | ||
<span style="color: #000000;">zmq_close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">subscriber</span><span style="color: #0000FF;">)</span> |
<span style="color: #000000;">zmq_close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">subscriber</span><span style="color: #0000FF;">)</span> |
||
<span style="color: #000000;">zmq_term</span><span style="color: #0000FF;">(</span><span style="color: #000000;">context</span><span style="color: #0000FF;">)</span> |
<span style="color: #000000;">zmq_term</span><span style="color: #0000FF;">(</span><span style="color: #000000;">context</span><span style="color: #0000FF;">)</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
===Server=== |
===Server=== |
||
< |
<syntaxhighlight lang="picolisp">(task (port 12321) # Background server task |
||
(let? Sock (accept @) |
(let? Sock (accept @) |
||
(unless (fork) # Handle request in child process |
(unless (fork) # Handle request in child process |
||
Line 1,272: | Line 1,272: | ||
(pr (eval @)) ) ) ) # Evaluate and send reply |
(pr (eval @)) ) ) ) # Evaluate and send reply |
||
(bye) ) # Exit child process |
(bye) ) # Exit child process |
||
(close Sock) ) ) # Close socket in parent process</ |
(close Sock) ) ) # Close socket in parent process</syntaxhighlight> |
||
===Client=== |
===Client=== |
||
< |
<syntaxhighlight lang="picolisp">(let? Sock (connect "localhost" 12321) |
||
(out Sock (pr '*Pid)) # Query PID from server |
(out Sock (pr '*Pid)) # Query PID from server |
||
(println 'PID (in Sock (rd))) # Receive and print reply |
(println 'PID (in Sock (rd))) # Receive and print reply |
||
(out Sock (pr '(* 3 4))) # Request some calculation |
(out Sock (pr '(* 3 4))) # Request some calculation |
||
(println 'Result (in Sock (rd))) # Print result |
(println 'Result (in Sock (rd))) # Print result |
||
(close Sock) ) # Close connection to server</ |
(close Sock) ) # Close connection to server</syntaxhighlight> |
||
Output: |
Output: |
||
<pre>PID 18372 |
<pre>PID 18372 |
||
Line 1,291: | Line 1,291: | ||
==== Server ==== |
==== Server ==== |
||
< |
<syntaxhighlight lang="python">#!/usr/bin/env python |
||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||
Line 1,328: | Line 1,328: | ||
except KeyboardInterrupt: |
except KeyboardInterrupt: |
||
print 'Exiting...' |
print 'Exiting...' |
||
server.server_close()</ |
server.server_close()</syntaxhighlight> |
||
==== Client ==== |
==== Client ==== |
||
< |
<syntaxhighlight lang="python">#!/usr/bin/env python |
||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||
Line 1,353: | Line 1,353: | ||
# control if foo_function returns True |
# control if foo_function returns True |
||
if rpc.foo_function(): |
if rpc.foo_function(): |
||
print 'Server says: foo_function returned True'</ |
print 'Server says: foo_function returned True'</syntaxhighlight> |
||
===HTTP=== |
===HTTP=== |
||
Line 1,359: | Line 1,359: | ||
==== Server ==== |
==== Server ==== |
||
< |
<syntaxhighlight lang="python">#!/usr/bin/python |
||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||
Line 1,388: | Line 1,388: | ||
except KeyboardInterrupt: |
except KeyboardInterrupt: |
||
print 'Exiting...' |
print 'Exiting...' |
||
server.server_close()</ |
server.server_close()</syntaxhighlight> |
||
==== Client ==== |
==== Client ==== |
||
< |
<syntaxhighlight lang="python">#!/usr/bin/python |
||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||
Line 1,405: | Line 1,405: | ||
print 'Server Status: %d' % response.status |
print 'Server Status: %d' % response.status |
||
print 'Server Message: %s' % response.read()</ |
print 'Server Message: %s' % response.read()</syntaxhighlight> |
||
===Socket, Pickle format=== |
===Socket, Pickle format=== |
||
Line 1,414: | Line 1,414: | ||
==== Server ==== |
==== Server ==== |
||
< |
<syntaxhighlight lang="python">#!/usr/bin/python |
||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||
Line 1,471: | Line 1,471: | ||
print 'Exiting...' |
print 'Exiting...' |
||
rpcserver.server_close() |
rpcserver.server_close() |
||
</syntaxhighlight> |
|||
</lang> |
|||
==== Client ==== |
==== Client ==== |
||
< |
<syntaxhighlight lang="python">#!/usr/bin/python |
||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||
Line 1,528: | Line 1,528: | ||
print '42/2 is:', rpcclient.div(divisor=2, dividend=42) |
print '42/2 is:', rpcclient.div(divisor=2, dividend=42) |
||
rpcclient._close() |
rpcclient._close() |
||
del rpcclient</ |
del rpcclient</syntaxhighlight> |
||
===Pyro=== |
===Pyro=== |
||
Line 1,534: | Line 1,534: | ||
==== Server ==== |
==== Server ==== |
||
< |
<syntaxhighlight lang="python">#!/usr/bin/python |
||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||
Line 1,559: | Line 1,559: | ||
except KeyboardInterrupt: |
except KeyboardInterrupt: |
||
print 'Exiting...' |
print 'Exiting...' |
||
server.shutdown()</ |
server.shutdown()</syntaxhighlight> |
||
==== Client ==== |
==== Client ==== |
||
< |
<syntaxhighlight lang="python">#!/usr/bin/python |
||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||
Line 1,578: | Line 1,578: | ||
print 'We sent two numbers to divide: %d and %d' % (NUM1, NUM2) |
print 'We sent two numbers to divide: %d and %d' % (NUM1, NUM2) |
||
print 'Server responded the result: %s' % math.div(NUM1, NUM2)</ |
print 'Server responded the result: %s' % math.div(NUM1, NUM2)</syntaxhighlight> |
||
=== Spread === |
=== Spread === |
||
Line 1,589: | Line 1,589: | ||
==== Client (Listener) ==== |
==== Client (Listener) ==== |
||
< |
<syntaxhighlight lang="python">#!/usr/bin/python |
||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||
Line 1,606: | Line 1,606: | ||
if hasattr(recv, 'sender') and hasattr(recv, 'message'): |
if hasattr(recv, 'sender') and hasattr(recv, 'message'): |
||
print 'Sender: %s' % recv.sender |
print 'Sender: %s' % recv.sender |
||
print 'Message: %s' % recv.message</ |
print 'Message: %s' % recv.message</syntaxhighlight> |
||
==== Client (Sender) ==== |
==== Client (Sender) ==== |
||
< |
<syntaxhighlight lang="python">#!/usr/bin/python |
||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||
Line 1,620: | Line 1,620: | ||
conn.multicast(spread.RELIABLE_MESS, 'test', 'hello, this is message sent from python') |
conn.multicast(spread.RELIABLE_MESS, 'test', 'hello, this is message sent from python') |
||
conn.disconnect()</ |
conn.disconnect()</syntaxhighlight> |
||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
Server and client in the same piece of code, running a useless (fib 42) computation, four times, on four hosts (which all happen to be "localhost", but that can change, of course). |
Server and client in the same piece of code, running a useless (fib 42) computation, four times, on four hosts (which all happen to be "localhost", but that can change, of course). |
||
< |
<syntaxhighlight lang="racket"> |
||
#lang racket/base |
#lang racket/base |
||
(require racket/place/distributed racket/place) |
(require racket/place/distributed racket/place) |
||
Line 1,650: | Line 1,650: | ||
(printf "Results: ~s\n" (map *channel-get places)) |
(printf "Results: ~s\n" (map *channel-get places)) |
||
(exit)))) |
(exit)))) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Raku}}== |
=={{header|Raku}}== |
||
Line 1,661: | Line 1,661: | ||
Usage: |
Usage: |
||
server.p6 [--server=<Any>] [--port=<Any>]</pre> |
server.p6 [--server=<Any>] [--port=<Any>]</pre> |
||
<lang |
<syntaxhighlight lang="raku" line>#!/usr/bin/env raku |
||
use JSON::Fast ; |
use JSON::Fast ; |
||
sub MAIN( :$server='0.0.0.0' , :$port=3333 ) { |
sub MAIN( :$server='0.0.0.0' , :$port=3333 ) { |
||
Line 1,696: | Line 1,696: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
client.raku: |
client.raku: |
||
<pre>Usage: |
<pre>Usage: |
||
Line 1,702: | Line 1,702: | ||
client.raku [--server=<Any>] [--port=<Any>] get <topic> |
client.raku [--server=<Any>] [--port=<Any>] get <topic> |
||
client.raku [--server=<Any>] [--port=<Any>] dump</pre> |
client.raku [--server=<Any>] [--port=<Any>] dump</pre> |
||
<lang |
<syntaxhighlight lang="raku" line>#!/usr/bin/env raku |
||
use JSON::Fast ; |
use JSON::Fast ; |
||
multi MAIN('set', $topic, $message='', :$server='localhost', :$port='3333', :$json='') { |
multi MAIN('set', $topic, $message='', :$server='localhost', :$port='3333', :$json='') { |
||
Line 1,730: | Line 1,730: | ||
} |
} |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
examples: |
examples: |
||
<pre>echo '{"function":"set","topic":"push","message":["perl5","raku","rakudo"]}' | nc localhost 3333 |
<pre>echo '{"function":"set","topic":"push","message":["perl5","raku","rakudo"]}' | nc localhost 3333 |
||
Line 1,757: | Line 1,757: | ||
'''Server''' |
'''Server''' |
||
< |
<syntaxhighlight lang="ruby">require 'drb/drb' |
||
# The URI for the server to connect to |
# The URI for the server to connect to |
||
Line 1,777: | Line 1,777: | ||
DRb.start_service(URI, FRONT_OBJECT) |
DRb.start_service(URI, FRONT_OBJECT) |
||
# Wait for the drb server thread to finish before exiting. |
# Wait for the drb server thread to finish before exiting. |
||
DRb.thread.join</ |
DRb.thread.join</syntaxhighlight> |
||
'''Client''' |
'''Client''' |
||
< |
<syntaxhighlight lang="ruby">require 'drb/drb' |
||
# The URI to connect to |
# The URI to connect to |
||
Line 1,793: | Line 1,793: | ||
timeserver = DRbObject.new_with_uri(SERVER_URI) |
timeserver = DRbObject.new_with_uri(SERVER_URI) |
||
puts timeserver.get_current_time</ |
puts timeserver.get_current_time</syntaxhighlight> |
||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
A rudimentary IRC Server |
A rudimentary IRC Server |
||
< |
<syntaxhighlight lang="tcl">proc main {} { |
||
global connections |
global connections |
||
set connections [dict create] |
set connections [dict create] |
||
Line 1,859: | Line 1,859: | ||
} |
} |
||
main</ |
main</syntaxhighlight> |
||
Client |
Client |
||
< |
<syntaxhighlight lang="tcl">proc main {} { |
||
global argv argc |
global argv argc |
||
if {$argc != 2} { |
if {$argc != 2} { |
||
Line 1,896: | Line 1,896: | ||
} |
} |
||
main</ |
main</syntaxhighlight> |
||
=={{header|UnixPipes}}== |
=={{header|UnixPipes}}== |
||
Line 1,905: | Line 1,905: | ||
{{alertbox|yellow|'''Security risk!''' Anything, able to reach 127.0.0.1 port 1234, can run shell commands as the user who runs the server. This allows other users to gain privileges.}} |
{{alertbox|yellow|'''Security risk!''' Anything, able to reach 127.0.0.1 port 1234, can run shell commands as the user who runs the server. This allows other users to gain privileges.}} |
||
< |
<syntaxhighlight lang="bash">: >/tmp/buffer |
||
tail -f /tmp/buffer | nc -l 127.0.0.1 1234 | sh >/tmp/buffer 2>&1</ |
tail -f /tmp/buffer | nc -l 127.0.0.1 1234 | sh >/tmp/buffer 2>&1</syntaxhighlight> |
||
Limitations: |
Limitations: |
||
Line 1,914: | Line 1,914: | ||
===Client=== |
===Client=== |
||
< |
<syntaxhighlight lang="bash">nc 127.0.0.1 1234</syntaxhighlight> |
||
Now you can enter commands in the client terminal and get the output back through the same connection. |
Now you can enter commands in the client terminal and get the output back through the same connection. |
||
Line 1,929: | Line 1,929: | ||
<br> |
<br> |
||
We need two Wren scripts one for each VM: |
We need two Wren scripts one for each VM: |
||
< |
<syntaxhighlight lang="ecmascript">/* distributed_programming_server.wren */ |
||
class Rpc { |
class Rpc { |
||
Line 1,948: | Line 1,948: | ||
Rpc.handleHTTP() |
Rpc.handleHTTP() |
||
var listener = Listener.listen("tcp", ":1234") |
var listener = Listener.listen("tcp", ":1234") |
||
HTTP.serve(listener)</ |
HTTP.serve(listener)</syntaxhighlight> |
||
<br> |
<br> |
||
< |
<syntaxhighlight lang="ecmascript">/* distributed_programming_server2.wren */ |
||
class TaxComputer { |
class TaxComputer { |
||
Line 1,957: | Line 1,957: | ||
return amount * rate |
return amount * rate |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
<br> |
<br> |
||
We now embed these scripts in the following Go program and run it on one terminal. |
We now embed these scripts in the following Go program and run it on one terminal. |
||
< |
<syntaxhighlight lang="go">/* go run distributed_programming_server.go */ |
||
package main |
package main |
||
Line 2,044: | Line 2,044: | ||
vm.Free() |
vm.Free() |
||
vm2.Free() |
vm2.Free() |
||
}</ |
}</syntaxhighlight> |
||
<br> |
<br> |
||
'''Client:''' |
'''Client:''' |
||
<br> |
<br> |
||
Just one Wren script needed here: |
Just one Wren script needed here: |
||
< |
<syntaxhighlight lang="ecmascript">/* distributed_programming_client.wren */ |
||
import "./fmt" for Fmt |
import "./fmt" for Fmt |
||
Line 2,064: | Line 2,064: | ||
var tax = client.call("TaxComputer.Tax", amount) |
var tax = client.call("TaxComputer.Tax", amount) |
||
Fmt.print("Tax on $0.2f = $0.2f", amount, tax) |
Fmt.print("Tax on $0.2f = $0.2f", amount, tax) |
||
}</ |
}</syntaxhighlight> |
||
<br> |
<br> |
||
which we embed in the following Go program and run it on a different terminal. |
which we embed in the following Go program and run it on a different terminal. |
||
< |
<syntaxhighlight lang="go">/* go run distributed_programming_client.go */ |
||
package main |
package main |
||
Line 2,122: | Line 2,122: | ||
vm.InterpretFile(fileName) |
vm.InterpretFile(fileName) |
||
vm.Free() |
vm.Free() |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |