Distributed programming: Difference between revisions

m
m (→‎{{header|Wren}}: Minor tidy)
 
(12 intermediate revisions by 7 users not shown)
Line 16:
 
server.ads:
<langsyntaxhighlight Adalang="ada">package Server is
pragma Remote_Call_Interface;
procedure Foo;
function Bar return Natural;
end Server;</langsyntaxhighlight>
 
server.adb:
<langsyntaxhighlight Adalang="ada">package body Server is
Count : Natural := 0;
 
Line 35:
return Count;
end Bar;
end Server;</langsyntaxhighlight>
 
client.adb:
<langsyntaxhighlight Adalang="ada">with Server;
with Ada.Text_IO;
 
Line 46:
Server.Foo;
Ada.Text_IO.Put_Line ("Calling Bar: " & Integer'Image (Server.Bar));
end Client;</langsyntaxhighlight>
 
required config (dsa.cfg):
<langsyntaxhighlight Adalang="ada">configuration DSA is
pragma Starter (None);
 
Line 61:
procedure Client;
for Client_Partition'Main use Client;
end DSA;</langsyntaxhighlight>
 
compilation:
Line 118:
 
=={{header|C}}==
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.
<langsyntaxhighlight Clang="c">#include <stdio.h>
#include <stdlib.h>
#include <pvm3.h>
Line 169:
pvm_exit();
return 0;
}</langsyntaxhighlight>Running{{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
[2]
Line 179:
[2:t40028] got msg type 1: 1804289383 0.394383
[2:t40028] EOF
[2] finished</langsyntaxhighlight>
 
=={{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.
 
<langsyntaxhighlight lang="csharp">
using System;
using System.IO;
Line 282:
public string Loot = "140 tonnes of jade";
}
</syntaxhighlight>
</lang>
 
=={{header|D}}==
Line 289:
 
This library is not standard, so this code (by Adam D. Ruppe) could and should be rewritten using more standard means.
<langsyntaxhighlight lang="d">import arsd.rpc;
 
struct S1 {
Line 355:
server.eventLoop;
}
}</langsyntaxhighlight>
 
=={{header|E}}==
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.)
 
<langsyntaxhighlight Elang="e">def storage := [].diverge()
 
def logService {
Line 384:
def sturdyRef := makeSturdyRef.temp(logService)
println(<captp>.sturdyToURI(sturdyRef))
interp.blockAtTop()</langsyntaxhighlight>
 
This will print the URL of the service and run it until aborted.
Line 392:
The URL provided by the server is given as the argument to this program.
 
<langsyntaxhighlight Elang="e">def [uri] := interp.getArgs()
introducer.onTheAir()
def sturdyRef := <captp>.sturdyFromURI(uri)
Line 405:
println(`At $time: $line`)
}
}</langsyntaxhighlight>
 
=={{header|Erlang}}==
Line 412:
srv.erl
 
<langsyntaxhighlight lang="erlang">-module(srv).
-export([start/0, wait/0]).
 
Line 430:
wait();
Any -> io:fwrite("Error ~p~n", [Any])
end.</langsyntaxhighlight>
 
=== Client ===
client.erl
 
<langsyntaxhighlight lang="erlang">-module(client).
-export([start/0, wait/0]).
 
Line 451:
{hello, Any} -> io:fwrite("Received ~p~n", [Any]);
Any -> io:fwrite("Error ~p~n", [Any])
end.</langsyntaxhighlight>
 
running it (*comes later)
Line 474:
 
===Server===
<langsyntaxhighlight lang="factor">USING: concurrency.distributed concurrency.messaging threads io.sockets io.servers ;
QUALIFIED: concurrency.messaging
: prettyprint-message ( -- ) concurrency.messaging:receive . flush prettyprint-message ;
[ prettyprint-message ] "logger" spawn dup name>> register-remote-thread
"127.0.0.1" 9000 <inet4> <node-server> start-server</langsyntaxhighlight>
 
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===
<langsyntaxhighlight lang="factor">USING: concurrency.distributed io.sockets ;
QUALIFIED: concurrency.messaging
{ "Hello Remote Factor!" H{ { "key1" "value1" } } }
"127.0.0.1" 9000 <inet4> "logger" <remote-thread> concurrency.messaging:send</langsyntaxhighlight>
 
How to Run:
Line 501:
 
'''Server:'''
<langsyntaxhighlight lang="go">package main
 
import (
Line 530:
}
http.Serve(listener, nil)
}</langsyntaxhighlight>
'''Client:'''
<langsyntaxhighlight lang="go">package main
 
import (
Line 554:
}
fmt.Printf("Tax on %.2f: %.2f\n", amount, tax)
}</langsyntaxhighlight>
{{out | Client output}}
<pre>
Line 565:
 
'''.proto:'''
<langsyntaxhighlight lang="proto">syntax = "proto3";
 
service TaxComputer {
Line 573:
message Amount {
int32 cents = 1;
}</langsyntaxhighlight>
'''Server:'''
<langsyntaxhighlight lang="go">package main
 
import (
Line 608:
taxcomputer.RegisterTaxComputerServer(grpcServer, &taxServer{.05})
grpcServer.Serve(listener)
}</langsyntaxhighlight>
'''Client:'''
<langsyntaxhighlight lang="go">package main
 
import (
Line 635:
}
fmt.Println("Tax on", amt.Cents, "cents is", tax.Cents, "cents")
}</langsyntaxhighlight>
{{out | Client output}}
<pre>
Line 647:
 
Like gRPC, Thrift requires a language independent interface definition file:
<langsyntaxhighlight lang="thrift">service TaxService {
i32 tax(1: i32 amt)
}</langsyntaxhighlight>
'''Server:'''
<langsyntaxhighlight lang="go">package main
 
import (
Line 683:
log.Fatal(err)
}
}</langsyntaxhighlight>
'''Client:'''
<langsyntaxhighlight lang="go">package main
 
import (
Line 714:
}
transport.Close()
}</langsyntaxhighlight>
{{out | Client output}}
<pre>
Line 735:
===Server===
 
<langsyntaxhighlight lang="javascript">var net = require('net')
 
var server = net.createServer(function (c){
Line 743:
 
server.listen(3000, 'localhost')
</syntaxhighlight>
</lang>
 
===Client===
<langsyntaxhighlight lang="javascript">var net = require('net')
 
conn = net.createConnection(3000, '192.168.1.x')
Line 757:
conn.on('data', function(msg){
console.log(msg.toString())
})</langsyntaxhighlight>
 
=={{header|Julia}}==
Line 763:
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:
<syntaxhighlight lang ="julia"># From Julia the 1.0's online docs. File countheads.jl available to all machines:
 
function count_heads(n)
Line 771:
end
c
end</langsyntaxhighlight>
We then run the following on the primary client:
<langsyntaxhighlight lang="julia">
using Distributed
@everywhere include_string(Main, $(read("count_heads.jl", String)), "count_heads.jl")
Line 780:
b = @spawn count_heads(100000000) # runs on another available processor
 
println(fetch(a)+fetch(b)) # total heads of 2200 million coin flips, half on each CPU
</langsyntaxhighlight> {{output}} <pre>
100001564
</pre>
Line 795:
In one terminal window, start up the REPL
 
<langsyntaxhighlight lang="bash">
$ ./bin/lfe
Erlang/OTP 17 [erts-6.2] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false]
Line 801:
LFE Shell V6.2 (abort with ^G)
>
</syntaxhighlight>
</lang>
 
And then enter the following code
 
<langsyntaxhighlight lang="lisp">
> (defun get-server-name ()
(list_to_atom (++ "exampleserver@" (element 2 (inet:gethostname)))))
Line 825:
(x
(io:format "Unexpected pattern: ~p~n" `(,x)))))
</syntaxhighlight>
</lang>
 
===Client===
Line 831:
In another terminal window, start up another LFE REPL and ender the following code:
 
<langsyntaxhighlight lang="lisp">
> (defun get-server-name ()
(list_to_atom (++ "exampleserver@" (element 2 (inet:gethostname)))))
Line 846:
(io:format "Unexpected pattern: ~p~n" (list x))))
'ok)
</syntaxhighlight>
</lang>
 
To use this code, simply start the server in the server terminal:
 
<langsyntaxhighlight lang="lisp">
> (start)
exampleserver@yourhostname ready
ok
(exampleserver@yourhostname)>
</syntaxhighlight>
</lang>
 
Send some messages from the client terminal:
 
<langsyntaxhighlight lang="lisp">
> (send "hi there")
connecting to exampleserver@yourhostname
Line 873:
ok
(exampleclient@yourhostname)>
</syntaxhighlight>
</lang>
 
And check out the results back in the server terminal window:
 
<langsyntaxhighlight lang="lisp">
Got "hi there" from exampleclient@yourhostname
Got 42 from exampleclient@yourhostname
Got {key,value} from exampleclient@yourhostname
</syntaxhighlight>
</lang>
 
=={{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.
<langsyntaxhighlight Mathematicalang="mathematica">LaunchKernels[2];
ParallelEvaluate[RandomReal[]]
</syntaxhighlight>
</lang>
 
=={{header|Nim}}==
{{libheader|nanomsg}}
<langsyntaxhighlight lang="nim">import os, nanomsg
 
proc sendMsg(s: cint, msg: string) =
echo "SENDING \"",msg,"\""
let bytes = s.send(msg.cstring, msg.len + 1, 0)
assert bytes == msg.len + 1
 
proc recvMsg(s: cint) =
var buf: cstring
let bytes = s.recv(addr buf, MSG, 0)
Line 905:
discard freemsg buf
 
proc sendRecv(s: cint, msg: string) =
var to: cint = 100
discard s.setSockOpt(SOL_SOCKET, RCVTIMEO, addr to, sizeof to)
Line 932:
node0 paramStr(2)
elif paramStr(1) == "node1":
node1 paramStr(2)</langsyntaxhighlight>
Usage:
<pre>./pair node0 tcp://127.0.0.1:25000
Line 945:
 
<tt>ActionObjectProtocol.h</tt>
<langsyntaxhighlight lang="objc">#import <Foundation/Foundation.h>
// our protocol allows "sending" "strings", but we can implement
// everything we could for a "local" object
@protocol ActionObjectProtocol
- (NSString *)sendMessage: (NSString *)msg;
@end</langsyntaxhighlight>
 
<tt>ActionObject.h</tt>
<langsyntaxhighlight lang="objc">#import <Foundation/Foundation.h>
#import "ActionObjectProtocol.h"
 
@interface ActionObject : NSObject <ActionObjectProtocol>
// we do not have much for this example!
@end</langsyntaxhighlight>
 
<tt>ActionObject.m</tt>
<langsyntaxhighlight lang="objc">#import <Foundation/Foundation.h>
#import "ActionObject.h"
 
Line 970:
return @"server answers ...";
}
@end</langsyntaxhighlight>
 
<tt>server.m</tt>
<langsyntaxhighlight lang="objc">#import <Foundation/Foundation.h>
#import "ActionObject.h"
 
Line 1,007:
}
return 0;
}</langsyntaxhighlight>
 
===Client===
<tt>client.m</tt>
<langsyntaxhighlight lang="objc">#import <Foundation/Foundation.h>
#import "ActionObjectProtocol.h"
 
Line 1,048:
}
return 0;
}</langsyntaxhighlight>
 
=={{header|OCaml}}==
Line 1,056:
 
=== Server ===
<langsyntaxhighlight lang="ocaml">open Printf
let create_logger () =
Line 1,078:
register "search" search;
Join.Site.listen (Unix.ADDR_INET (Join.Site.get_local_addr(), 12345));
wait ()</langsyntaxhighlight>
 
=== Client ===
 
<langsyntaxhighlight lang="ocaml">open Printf
let ns_there = Join.Ns.there (Unix.ADDR_INET (Join.Site.get_local_addr(), 12345))
Line 1,102:
log "foo";
log "shoe";
find "foo"</langsyntaxhighlight>
 
=={{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.
 
<langsyntaxhighlight lang="oz">declare
functor ServerCode
export
Line 1,146:
 
%% shut down server
{RM close}</langsyntaxhighlight>
 
=={{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.
<syntaxhighlight lang="perl">use strict;
<lang Perl>use Data::Dumper;
use warnings;
use Data::Dumper;
use IO::Socket::INET;
use Safe;
 
sub get_data {
my $sock = new IO::Socket::INET->new(
LocalHost => "localhost",
LocalPort => "10000",
Proto => "tcp",
Listen => 1,
Reuse => 1);
unless ($sock) { die "Socket creation failure" }
my $cli = $sock->accept();
Line 1,166 ⟶ 1,168:
# of course someone may be tempted to send you 'system("rm -rf /")',
# to be safe(r), use Safe::
my $safe = new Safe->new;
my $x = $safe->reval(join("", <$cli>));
close $cli;
Line 1,176 ⟶ 1,178:
my $host = shift;
my $data = shift;
my $sock = new IO::Socket::INET->new(
PeerAddr => "$host:10000",
Proto => "tcp",
Reuse => 1);
 
unless ($sock) { die "Socket creation failure" }
Line 1,192 ⟶ 1,194:
} else {
send_data('some_host', { a=>100, b=>[1 .. 10] });
}</langsyntaxhighlight>
=={{header|Perl 6}}==
Server listens for JSON encoded messages. It processes requests for set|get|dump. 'set' stores a message, 'get' returns message, 'dump' returns all stored messages. Optional parameters for ip address and port.
 
=={{header|Phix}}==
Server.p6:
From/using [http://phix.x10.mx/pmwiki/pmwiki.php?n=Main.Libzmq the ZeroMQ wrapper from PCAN], a suitable simple publish/subscriber pair.
<pre>./server.p6 --usage
There is also a server/client/broker example.
Usage:
Obviously you can trivially serialize() and deserialize() any Phix data to and from a string.
server.p6 [--server=<Any>] [--port=<Any>]</pre>
<!--<syntaxhighlight lang="phix">(notonline)-->
<lang perl6>#!/usr/bin/env perl6
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (zmq dll/so)</span>
use JSON::Fast ;
<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>
sub MAIN( :$server='0.0.0.0' , :$port=3333 ) {
<span style="color: #008080;">include</span> <span style="color: #000000;">zmq</span><span style="color: #0000FF;">/</span><span style="color: #000000;">zmq</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
my %db ;
react {
<span style="color: #004080;">atom</span> <span style="color: #000000;">context</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">zmq_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
whenever IO::Socket::Async.listen( $server , $port ) -> $conn {
<span style="color: #000000;">zmq_assert</span><span style="color: #0000FF;">(</span><span style="color: #000000;">context</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"zmq_init"</span><span style="color: #0000FF;">)</span>
whenever $conn.Supply.lines -> $line {
my %response = 'status' => '' ;
<span style="color: #000080;font-style:italic;">--// subscriber tells us when it's ready here</span>
my $msg = from-json $line ;
<span style="color: #004080;">atom</span> <span style="color: #000000;">sync</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">zmq_socket</span><span style="color: #0000FF;">(</span><span style="color: #000000;">context</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ZMQ_PULL</span><span style="color: #0000FF;">)</span>
say $msg.perl ;
<span style="color: #000000;">zmq_bind</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sync</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"tcp://*:5564"</span><span style="color: #0000FF;">)</span>
given $msg{"function"} {
when 'set' {
<span style="color: #000080;font-style:italic;">--// send update via this socket</span>
%db{ $msg<topic> } = $msg<message> ;
<span style="color: #004080;">atom</span> <span style="color: #000000;">publisher</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">zmq_socket</span><span style="color: #0000FF;">(</span><span style="color: #000000;">context</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ZMQ_PUB</span><span style="color: #0000FF;">)</span>
%response<status> = 'ok' ;
<span style="color: #000000;">zmq_bind</span><span style="color: #0000FF;">(</span><span style="color: #000000;">publisher</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"tcp://*:5565"</span><span style="color: #0000FF;">)</span>
}
when 'get' {
<span style="color: #000080;font-style:italic;">--// broadcast 10 updates, with pause</span>
%response<topic> = $msg<topic> ;
<span style="color: #008080;">for</span> <span style="color: #000000;">update_nbr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
%response<message> = %db{ $msg<topic> } ;
<span style="color: #004080;">string</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sprintf</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Update %d"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">update_nbr</span> <span style="color: #0000FF;">})</span>
%response<status> = 'ok' ;
<span style="color: #000000;">zmq_s_send</span><span style="color: #0000FF;">(</span><span style="color: #000000;">publisher</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
}
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
when 'dump' {
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
%response = %db ;
}
<span style="color: #000000;">zmq_s_send</span><span style="color: #0000FF;">(</span><span style="color: #000000;">publisher</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"END"</span><span style="color: #0000FF;">)</span>
when 'delete' {
<span style="color: #7060A8;">sleep</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
%db{ $msg<topic> }:delete;
%response<status> = 'ok' ;
<span style="color: #000000;">zmq_close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sync</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>
$conn.print( to-json(%response, :!pretty) ~ "\n" ) ;
<!--</syntaxhighlight>-->
LAST { $conn.close ; }
QUIT { default { $conn.close ; say "oh no, $_";}}
CATCH { default { say .^name, ': ', .Str , " handled in $?LINE";}}
}
}
}
}</lang>
client.p6:
<pre>Usage:
client.p6 [--server=<Any>] [--port=<Any>] [--json=<Any>] set <topic> [<message>]
client.p6 [--server=<Any>] [--port=<Any>] get <topic>
client.p6 [--server=<Any>] [--port=<Any>] dump</pre>
<lang perl6>#!/usr/bin/env perl6
use JSON::Fast ;
multi MAIN('set', $topic, $message='', :$server='localhost', :$port='3333', :$json='') {
my %msg = function => 'set' , topic=> $topic , message=> $message ;
%msg{"message"} = from-json( $json ) if $json ;
sendmsg( %msg , $server, $port) ;
}
multi MAIN('get', $topic, :$server='localhost', :$port='3333') {
my %msg = function => 'get' , topic=> $topic ;
sendmsg( %msg , $server, $port) ;
}
multi MAIN('delete', $topic, :$server='localhost', :$port='3333') {
my %msg = function => 'delete' , topic=> $topic ;
sendmsg( %msg , $server, $port) ;
}
multi MAIN('dump', :$server='localhost', :$port='3333') {
my %msg = function => 'dump' ;
sendmsg( %msg , $server, $port) ;
}
sub sendmsg( %msg , $server, $port){
my $conn = await IO::Socket::Async.connect( $server , $port );
$conn.print: to-json( %msg,:!pretty)~"\n";
react {
whenever $conn.Supply -> $data {
print $data;
$conn.close;
}
}
}</lang>
examples:
<pre>echo '{"function":"set","topic":"push","message":["perl5","perl6","rakudo"]}' | nc localhost 3333
 
<!--<syntaxhighlight lang="phix">(notonline)-->
./client.p6 set version perl6
<span style="color: #008080;">without</span> <span style="color: #008080;">js</span> <span style="color: #000080;font-style:italic;">-- (zmq dll/so)</span>
{"status": "ok"}
<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>
./client.p6 get version
<span style="color: #008080;">include</span> <span style="color: #000000;">zmq</span><span style="color: #0000FF;">/</span><span style="color: #000000;">zmq</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
{"status": "ok","topic": "version","message": "perl6"}
./client.p6 --json='["one","two","three"]' set mylist
<span style="color: #004080;">atom</span> <span style="color: #000000;">context</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">zmq_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
{"status": "ok"}
<span style="color: #000000;">zmq_assert</span><span style="color: #0000FF;">(</span><span style="color: #000000;">context</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"zmq_init"</span><span style="color: #0000FF;">)</span>
./client.p6 dump
{"push": ["perl5","perl6","rakudo"],"version": "perl6","mylist": ["one","two","three"]}
<span style="color: #000080;font-style:italic;">--// connect our subscriber socket</span>
./client.p6 delete version
<span style="color: #004080;">atom</span> <span style="color: #000000;">subscriber</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">zmq_socket</span><span style="color: #0000FF;">(</span><span style="color: #000000;">context</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ZMQ_SUB</span><span style="color: #0000FF;">)</span>
{"status": "ok"}
<span style="color: #004080;">atom</span> <span style="color: #000000;">id</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">allocate_string</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"Hello"</span><span style="color: #0000FF;">)</span>
 
<span style="color: #000000;">zmq_setsockopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">subscriber</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ZMQ_IDENTITY</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">id</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">)</span>
server output:
<span style="color: #000000;">zmq_setsockopt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">subscriber</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ZMQ_SUBSCRIBE</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
${:function("set"), :message($["perl5", "perl6", "rakudo"]), :topic("push")}
<span style="color: #000000;">zmq_connect</span><span style="color: #0000FF;">(</span><span style="color: #000000;">subscriber</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"tcp://localhost:5565"</span><span style="color: #0000FF;">)</span>
${:function("set"), :message("perl6"), :topic("version")}
<span style="color: #7060A8;">free</span><span style="color: #0000FF;">(</span><span style="color: #000000;">id</span><span style="color: #0000FF;">)</span>
${:function("get"), :topic("version")}
${:function("set"), :message($["one", "two", "three"]), :topic("mylist")}
<span style="color: #000080;font-style:italic;">--// synchronise with publisher</span>
${:function("dump")}
<span style="color: #004080;">atom</span> <span style="color: #000000;">sync</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">zmq_socket</span><span style="color: #0000FF;">(</span><span style="color: #000000;">context</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">ZMQ_PUSH</span><span style="color: #0000FF;">)</span>
${:function("delete"), :topic("version")}
<span style="color: #000000;">zmq_connect</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sync</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"tcp://localhost:5564"</span><span style="color: #0000FF;">)</span>
</pre>
<span style="color: #000000;">zmq_s_send</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sync</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">""</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">--// get updates, Ctrl-C break</span>
<span style="color: #008080;">while</span> <span style="color: #004600;">true</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">zmq_s_recv</span><span style="color: #0000FF;">(</span><span style="color: #000000;">subscriber</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"%s\n"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">s</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">==</span><span style="color: #008000;">"END"</span> <span style="color: #008080;">then</span> <span style="color: #008080;">exit</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
<span style="color: #000000;">zmq_close</span><span style="color: #0000FF;">(</span><span style="color: #000000;">sync</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>
<!--</syntaxhighlight>-->
 
=={{header|PicoLisp}}==
===Server===
<langsyntaxhighlight PicoLisplang="picolisp">(task (port 12321) # Background server task
(let? Sock (accept @)
(unless (fork) # Handle request in child process
Line 1,303 ⟶ 1,274:
(pr (eval @)) ) ) ) # Evaluate and send reply
(bye) ) # Exit child process
(close Sock) ) ) # Close socket in parent process</langsyntaxhighlight>
===Client===
<langsyntaxhighlight PicoLisplang="picolisp">(let? Sock (connect "localhost" 12321)
(out Sock (pr '*Pid)) # Query PID from server
(println 'PID (in Sock (rd))) # Receive and print reply
(out Sock (pr '(* 3 4))) # Request some calculation
(println 'Result (in Sock (rd))) # Print result
(close Sock) ) # Close connection to server</langsyntaxhighlight>
Output:
<pre>PID 18372
Line 1,322 ⟶ 1,293:
 
==== Server ====
<langsyntaxhighlight lang="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
Line 1,359 ⟶ 1,330:
except KeyboardInterrupt:
print 'Exiting...'
server.server_close()</langsyntaxhighlight>
 
==== Client ====
<langsyntaxhighlight lang="python">#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
Line 1,384 ⟶ 1,355:
# control if foo_function returns True
if rpc.foo_function():
print 'Server says: foo_function returned True'</langsyntaxhighlight>
 
===HTTP===
Line 1,390 ⟶ 1,361:
 
==== Server ====
<langsyntaxhighlight lang="python">#!/usr/bin/python
# -*- coding: utf-8 -*-
 
Line 1,419 ⟶ 1,390:
except KeyboardInterrupt:
print 'Exiting...'
server.server_close()</langsyntaxhighlight>
 
==== Client ====
<langsyntaxhighlight lang="python">#!/usr/bin/python
# -*- coding: utf-8 -*-
 
Line 1,436 ⟶ 1,407:
print 'Server Status: %d' % response.status
 
print 'Server Message: %s' % response.read()</langsyntaxhighlight>
 
===Socket, Pickle format===
Line 1,445 ⟶ 1,416:
 
==== Server ====
<langsyntaxhighlight lang="python">#!/usr/bin/python
# -*- coding: utf-8 -*-
Line 1,502 ⟶ 1,473:
print 'Exiting...'
rpcserver.server_close()
</syntaxhighlight>
</lang>
 
==== Client ====
<langsyntaxhighlight lang="python">#!/usr/bin/python
# -*- coding: utf-8 -*-
Line 1,559 ⟶ 1,530:
print '42/2 is:', rpcclient.div(divisor=2, dividend=42)
rpcclient._close()
del rpcclient</langsyntaxhighlight>
 
===Pyro===
Line 1,565 ⟶ 1,536:
 
==== Server ====
<langsyntaxhighlight lang="python">#!/usr/bin/python
# -*- coding: utf-8 -*-
 
Line 1,590 ⟶ 1,561:
except KeyboardInterrupt:
print 'Exiting...'
server.shutdown()</langsyntaxhighlight>
 
==== Client ====
<langsyntaxhighlight lang="python">#!/usr/bin/python
# -*- coding: utf-8 -*-
 
Line 1,609 ⟶ 1,580:
 
print 'We sent two numbers to divide: %d and %d' % (NUM1, NUM2)
print 'Server responded the result: %s' % math.div(NUM1, NUM2)</langsyntaxhighlight>
 
=== Spread ===
Line 1,620 ⟶ 1,591:
 
==== Client (Listener) ====
<langsyntaxhighlight lang="python">#!/usr/bin/python
# -*- coding: utf-8 -*-
 
Line 1,637 ⟶ 1,608:
if hasattr(recv, 'sender') and hasattr(recv, 'message'):
print 'Sender: %s' % recv.sender
print 'Message: %s' % recv.message</langsyntaxhighlight>
 
==== Client (Sender) ====
<langsyntaxhighlight lang="python">#!/usr/bin/python
# -*- coding: utf-8 -*-
 
Line 1,651 ⟶ 1,622:
 
conn.multicast(spread.RELIABLE_MESS, 'test', 'hello, this is message sent from python')
conn.disconnect()</langsyntaxhighlight>
 
=={{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).
 
<langsyntaxhighlight lang="racket">
#lang racket/base
(require racket/place/distributed racket/place)
Line 1,681 ⟶ 1,652:
(printf "Results: ~s\n" (map *channel-get places))
(exit))))
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
 
Server listens for JSON encoded messages. It processes requests for set|get|dump. 'set' stores a message, 'get' returns message, 'dump' returns all stored messages. Optional parameters for ip address and port.
 
Server.raku:
<pre>./server.raku --usage
Usage:
server.p6 [--server=<Any>] [--port=<Any>]</pre>
<syntaxhighlight lang="raku" line>#!/usr/bin/env raku
use JSON::Fast ;
sub MAIN( :$server='0.0.0.0' , :$port=3333 ) {
my %db ;
react {
whenever IO::Socket::Async.listen( $server , $port ) -> $conn {
whenever $conn.Supply.lines -> $line {
my %response = 'status' => '' ;
my $msg = from-json $line ;
say $msg.raku;
given $msg{"function"} {
when 'set' {
%db{ $msg<topic> } = $msg<message> ;
%response<status> = 'ok' ;
}
when 'get' {
%response<topic> = $msg<topic> ;
%response<message> = %db{ $msg<topic> } ;
%response<status> = 'ok' ;
}
when 'dump' {
%response = %db ;
}
when 'delete' {
%db{ $msg<topic> }:delete;
%response<status> = 'ok' ;
}
}
$conn.print( to-json(%response, :!pretty) ~ "\n" ) ;
LAST { $conn.close ; }
QUIT { default { $conn.close ; say "oh no, $_";}}
CATCH { default { say .^name, ': ', .Str , " handled in $?LINE";}}
}
}
}
}</syntaxhighlight>
client.raku:
<pre>Usage:
client.raku [--server=<Any>] [--port=<Any>] [--json=<Any>] set <topic> [<message>]
client.raku [--server=<Any>] [--port=<Any>] get <topic>
client.raku [--server=<Any>] [--port=<Any>] dump</pre>
<syntaxhighlight lang="raku" line>#!/usr/bin/env raku
use JSON::Fast ;
multi MAIN('set', $topic, $message='', :$server='localhost', :$port='3333', :$json='') {
my %msg = function => 'set' , topic=> $topic , message=> $message ;
%msg{"message"} = from-json( $json ) if $json ;
sendmsg( %msg , $server, $port) ;
}
multi MAIN('get', $topic, :$server='localhost', :$port='3333') {
my %msg = function => 'get' , topic=> $topic ;
sendmsg( %msg , $server, $port) ;
}
multi MAIN('delete', $topic, :$server='localhost', :$port='3333') {
my %msg = function => 'delete' , topic=> $topic ;
sendmsg( %msg , $server, $port) ;
}
multi MAIN('dump', :$server='localhost', :$port='3333') {
my %msg = function => 'dump' ;
sendmsg( %msg , $server, $port) ;
}
sub sendmsg( %msg , $server, $port){
my $conn = await IO::Socket::Async.connect( $server , $port );
$conn.print: to-json( %msg,:!pretty)~"\n";
react {
whenever $conn.Supply -> $data {
print $data;
$conn.close;
}
}
}</syntaxhighlight>
examples:
<pre>echo '{"function":"set","topic":"push","message":["perl5","raku","rakudo"]}' | nc localhost 3333
 
./client.raku set version raku
{"status": "ok"}
./client.raku get version
{"status": "ok","topic": "version","message": "raku"}
./client.raku --json='["one","two","three"]' set mylist
{"status": "ok"}
./client.raku dump
{"push": ["perl5","raku","rakudo"],"version": "raku","mylist": ["one","two","three"]}
./client.raku delete version
{"status": "ok"}
 
server output:
${:function("set"), :message($["perl5", "raku", "rakudo"]), :topic("push")}
${:function("set"), :message("raku"), :topic("version")}
${:function("get"), :topic("version")}
${:function("set"), :message($["one", "two", "three"]), :topic("mylist")}
${:function("dump")}
${:function("delete"), :topic("version")}</pre>
 
=={{header|Ruby}}==
Line 1,687 ⟶ 1,759:
 
'''Server'''
<langsyntaxhighlight lang="ruby">require 'drb/drb'
 
# The URI for the server to connect to
Line 1,707 ⟶ 1,779:
DRb.start_service(URI, FRONT_OBJECT)
# Wait for the drb server thread to finish before exiting.
DRb.thread.join</langsyntaxhighlight>
 
'''Client'''
<langsyntaxhighlight lang="ruby">require 'drb/drb'
 
# The URI to connect to
Line 1,723 ⟶ 1,795:
 
timeserver = DRbObject.new_with_uri(SERVER_URI)
puts timeserver.get_current_time</langsyntaxhighlight>
 
=={{header|Tcl}}==
A rudimentary IRC Server
<langsyntaxhighlight lang="tcl">proc main {} {
global connections
set connections [dict create]
Line 1,789 ⟶ 1,861:
}
 
main</langsyntaxhighlight>
Client
<langsyntaxhighlight lang="tcl">proc main {} {
global argv argc
if {$argc != 2} {
Line 1,826 ⟶ 1,898:
}
 
main</langsyntaxhighlight>
 
=={{header|UnixPipes}}==
Line 1,835 ⟶ 1,907:
{{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.}}
 
<langsyntaxhighlight lang="bash">: >/tmp/buffer
tail -f /tmp/buffer | nc -l 127.0.0.1 1234 | sh >/tmp/buffer 2>&1</langsyntaxhighlight>
 
Limitations:
Line 1,844 ⟶ 1,916:
 
===Client===
<langsyntaxhighlight lang="bash">nc 127.0.0.1 1234</langsyntaxhighlight>
 
Now you can enter commands in the client terminal and get the output back through the same connection.
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|WrenGo}}
{{libheader|Wren-fmt}}
As Wren has no networking support at present, we use embedded programs for both the server and client with a Go host using the net/rpc package in its standard library.
 
Moreover, as Wren's VM is not re-entrant, we need to run two VMs from the server side, one to call Go from Wren and the other to call Wren from Go.
 
'''Server:'''
<br>
We need two Wren scripts one for each VM:
<syntaxhighlight lang="wren">/* Distributed_programming_server.wren */
 
class Rpc {
foreign static register()
 
foreign static handleHTTP()
}
 
foreign class Listener {
construct listen(network, address) {}
}
 
class HTTP {
foreign static serve(listener)
}
 
Rpc.register()
Rpc.handleHTTP()
var listener = Listener.listen("tcp", ":1234")
HTTP.serve(listener)</syntaxhighlight>
<br>
<syntaxhighlight lang="wren">/* Distributed_programming_server_2.wren */
 
class TaxComputer {
static tax(amount, rate) {
if (amount < 0) Fiber.abort("Negative values not allowed.")
return amount * rate
}
}</syntaxhighlight>
<br>
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
 
import(
wren "github.com/crazyinfin8/WrenGo"
"log"
"net"
"net/http"
"net/rpc"
)
 
type any = interface{}
 
type TaxComputer float64
 
var vm2 *wren.VM
 
var fileName = "Distributed_programming_server.wren"
var fileName2 = "Distributed_programming_server_2.wren"
 
func (taxRate TaxComputer) Tax(x float64, r *float64) error {
wrenVar, _ := vm2.GetVariable(fileName2, "TaxComputer")
wrenClass, _ := wrenVar.(*wren.Handle)
defer wrenClass.Free()
wrenMethod, _ := wrenClass.Func("tax(_,_)")
defer wrenMethod.Free()
ret, _ := wrenMethod.Call(x, float64(taxRate))
*r = ret.(float64)
return nil
}
 
func register(vm *wren.VM, parameters []any) (any, error) {
c := TaxComputer(0.05) // 5% tax rate
rpc.Register(c)
return nil, nil
}
 
func handleHTTP(vm *wren.VM, parameters []any) (any, error) {
rpc.HandleHTTP()
return nil, nil
}
 
func serve(vm *wren.VM, parameters []any) (any, error) {
handle := parameters[1].(*wren.ForeignHandle)
ifc, _ := handle.Get()
listener := ifc.(*net.Listener)
http.Serve(*listener, nil)
return nil, nil
}
 
func listen(vm *wren.VM, parameters []any) (any, error) {
network := parameters[1].(string)
address := parameters[2].(string)
listener, err := net.Listen(network, address)
if err != nil {
log.Fatal(err)
}
return &listener, nil
}
 
func main() {
vm := wren.NewVM()
vm2 = wren.NewVM()
vm2.InterpretFile(fileName2)
 
rpcMethodMap := wren.MethodMap {
"static register()": register,
"static handleHTTP()": handleHTTP,
}
 
httpMethodMap := wren.MethodMap { "static serve(_)":serve }
 
classMap := wren.ClassMap {
"Listener": wren.NewClass(listen, nil, nil),
"Rpc" : wren.NewClass(nil, nil, rpcMethodMap),
"HTTP" : wren.NewClass(nil, nil, httpMethodMap),
}
 
module := wren.NewModule(classMap)
vm.SetModule(fileName, module)
vm.InterpretFile(fileName)
vm.Free()
vm2.Free()
}</syntaxhighlight>
<br>
'''Client:'''
<br>
Just one Wren script needed here:
<syntaxhighlight lang="wren">/* Distributed_programming_client.wren */
 
import "./fmt" for Fmt
 
foreign class Client {
construct dialHTTP(network, address) {}
 
foreign call(serviceMethod, arg)
}
 
var client = Client.dialHTTP("tcp", "localhost:1234")
var amounts = [3, 5.6]
for (amount in amounts) {
var tax = client.call("TaxComputer.Tax", amount)
Fmt.print("Tax on $0.2f = $0.2f", amount, tax)
}</syntaxhighlight>
<br>
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
 
import(
wren "github.com/crazyinfin8/WrenGo"
"log"
"net/rpc"
"strings"
)
 
type any = interface{}
 
func dialHTTP(vm *wren.VM, parameters []any) (any, error) {
network := parameters[1].(string)
address := parameters[2].(string)
client, err := rpc.DialHTTP(network, address)
if err != nil {
log.Fatal(err)
}
return &client, nil
}
 
func call(vm *wren.VM, parameters []any) (any, error) {
handle := parameters[0].(*wren.ForeignHandle)
ifc, _ := handle.Get()
client := ifc.(**rpc.Client)
serviceMethod := parameters[1].(string)
amount := parameters[2].(float64)
var tax float64
err := (*client).Call(serviceMethod, amount, &tax)
if err != nil {
log.Fatal(err)
}
return tax, nil
}
 
func moduleFn(vm *wren.VM, name string) (string, bool) {
if name != "meta" && name != "random" && !strings.HasSuffix(name, ".wren") {
name += ".wren"
}
return wren.DefaultModuleLoader(vm, name)
}
 
func main() {
cfg := wren.NewConfig()
cfg.LoadModuleFn = moduleFn
vm := cfg.NewVM()
fileName := "Distributed_programming_client.wren"
clientMethodMap := wren.MethodMap { "call(_,_)": call }
classMap := wren.ClassMap { "Client": wren.NewClass(dialHTTP, nil, clientMethodMap) }
module := wren.NewModule(classMap)
vm.SetModule(fileName, module)
vm.InterpretFile(fileName)
vm.Free()
}</syntaxhighlight>
 
{{out}}
Output on the client terminal:
<pre>
Tax on 3.00 = 0.15
Tax on 5.60 = 0.28
</pre>
 
{{omit from|Lotus 123 Macro Scripting}}
9,482

edits