Distributed programming: Difference between revisions
m
syntax highlighting fixup automation
m (→{{header|Phix}}: marked p2js incompatible) |
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
||
Line 16:
server.ads:
<
pragma Remote_Call_Interface;
procedure Foo;
function Bar return Natural;
end Server;</
server.adb:
<
Count : Natural := 0;
Line 35:
return Count;
end Bar;
end Server;</
client.adb:
<
with Ada.Text_IO;
Line 46:
Server.Foo;
Ada.Text_IO.Put_Line ("Calling Bar: " & Integer'Image (Server.Bar));
end Client;</
required config (dsa.cfg):
<
pragma Starter (None);
Line 61:
procedure Client;
for Client_Partition'Main use Client;
end DSA;</
compilation:
Line 120:
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.
<
#include <stdlib.h>
#include <pvm3.h>
Line 169:
pvm_exit();
return 0;
}</
spawn -> /tmp/a.out 1
[2]
Line 179:
[2:t40028] got msg type 1: 1804289383 0.394383
[2:t40028] EOF
[2] finished</
=={{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.
<
using System;
using System.IO;
Line 282:
public string Loot = "140 tonnes of jade";
}
</syntaxhighlight>
=={{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.
<
struct S1 {
Line 355:
server.eventLoop;
}
}</
=={{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.)
<
def logService {
Line 384:
def sturdyRef := makeSturdyRef.temp(logService)
println(<captp>.sturdyToURI(sturdyRef))
interp.blockAtTop()</
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.
<
introducer.onTheAir()
def sturdyRef := <captp>.sturdyFromURI(uri)
Line 405:
println(`At $time: $line`)
}
}</
=={{header|Erlang}}==
Line 412:
srv.erl
<
-export([start/0, wait/0]).
Line 430:
wait();
Any -> io:fwrite("Error ~p~n", [Any])
end.</
=== Client ===
client.erl
<
-export([start/0, wait/0]).
Line 451:
{hello, Any} -> io:fwrite("Received ~p~n", [Any]);
Any -> io:fwrite("Error ~p~n", [Any])
end.</
running it (*comes later)
Line 474:
===Server===
<
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</
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===
<
QUALIFIED: concurrency.messaging
{ "Hello Remote Factor!" H{ { "key1" "value1" } } }
"127.0.0.1" 9000 <inet4> "logger" <remote-thread> concurrency.messaging:send</
How to Run:
Line 501:
'''Server:'''
<
import (
Line 530:
}
http.Serve(listener, nil)
}</
'''Client:'''
<
import (
Line 554:
}
fmt.Printf("Tax on %.2f: %.2f\n", amount, tax)
}</
{{out | Client output}}
<pre>
Line 565:
'''.proto:'''
<
service TaxComputer {
Line 573:
message Amount {
int32 cents = 1;
}</
'''Server:'''
<
import (
Line 608:
taxcomputer.RegisterTaxComputerServer(grpcServer, &taxServer{.05})
grpcServer.Serve(listener)
}</
'''Client:'''
<
import (
Line 635:
}
fmt.Println("Tax on", amt.Cents, "cents is", tax.Cents, "cents")
}</
{{out | Client output}}
<pre>
Line 647:
Like gRPC, Thrift requires a language independent interface definition file:
<
i32 tax(1: i32 amt)
}</
'''Server:'''
<
import (
Line 683:
log.Fatal(err)
}
}</
'''Client:'''
<
import (
Line 714:
}
transport.Close()
}</
{{out | Client output}}
<pre>
Line 735:
===Server===
<
var server = net.createServer(function (c){
Line 743:
server.listen(3000, 'localhost')
</syntaxhighlight>
===Client===
<
conn = net.createConnection(3000, '192.168.1.x')
Line 757:
conn.on('data', function(msg){
console.log(msg.toString())
})</
=={{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:
<
function count_heads(n)
Line 771:
end
c
end</
We then run the following on the primary client:
<
using Distributed
@everywhere include_string(Main, $(read("count_heads.jl", String)), "count_heads.jl")
Line 781:
println(fetch(a)+fetch(b)) # total heads of 200 million coin flips, half on each CPU
</
100001564
</pre>
Line 795:
In one terminal window, start up the REPL
<
$ ./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>
And then enter the following code
<
> (defun get-server-name ()
(list_to_atom (++ "exampleserver@" (element 2 (inet:gethostname)))))
Line 825:
(x
(io:format "Unexpected pattern: ~p~n" `(,x)))))
</syntaxhighlight>
===Client===
Line 831:
In another terminal window, start up another LFE REPL and ender the following code:
<
> (defun get-server-name ()
(list_to_atom (++ "exampleserver@" (element 2 (inet:gethostname)))))
Line 846:
(io:format "Unexpected pattern: ~p~n" (list x))))
'ok)
</syntaxhighlight>
To use this code, simply start the server in the server terminal:
<
> (start)
exampleserver@yourhostname ready
ok
(exampleserver@yourhostname)>
</syntaxhighlight>
Send some messages from the client terminal:
<
> (send "hi there")
connecting to exampleserver@yourhostname
Line 873:
ok
(exampleclient@yourhostname)>
</syntaxhighlight>
And check out the results back in the server terminal window:
<
Got "hi there" from exampleclient@yourhostname
Got 42 from exampleclient@yourhostname
Got {key,value} from exampleclient@yourhostname
</syntaxhighlight>
=={{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.
<
ParallelEvaluate[RandomReal[]]
</syntaxhighlight>
=={{header|Nim}}==
{{libheader|nanomsg}}
<
proc sendMsg(s: cint, msg: string) =
Line 932:
node0 paramStr(2)
elif paramStr(1) == "node1":
node1 paramStr(2)</
Usage:
<pre>./pair node0 tcp://127.0.0.1:25000
Line 945:
<tt>ActionObjectProtocol.h</tt>
<
// our protocol allows "sending" "strings", but we can implement
// everything we could for a "local" object
@protocol ActionObjectProtocol
- (NSString *)sendMessage: (NSString *)msg;
@end</
<tt>ActionObject.h</tt>
<
#import "ActionObjectProtocol.h"
@interface ActionObject : NSObject <ActionObjectProtocol>
// we do not have much for this example!
@end</
<tt>ActionObject.m</tt>
<
#import "ActionObject.h"
Line 970:
return @"server answers ...";
}
@end</
<tt>server.m</tt>
<
#import "ActionObject.h"
Line 1,007:
}
return 0;
}</
===Client===
<tt>client.m</tt>
<
#import "ActionObjectProtocol.h"
Line 1,048:
}
return 0;
}</
=={{header|OCaml}}==
Line 1,056:
=== Server ===
<
let create_logger () =
Line 1,078:
register "search" search;
Join.Site.listen (Unix.ADDR_INET (Join.Site.get_local_addr(), 12345));
wait ()</
=== Client ===
<
let ns_there = Join.Ns.there (Unix.ADDR_INET (Join.Site.get_local_addr(), 12345))
Line 1,102:
log "foo";
log "shoe";
find "foo"</
=={{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.
<
functor ServerCode
export
Line 1,146:
%% shut down server
{RM close}</
=={{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.
<
use IO::Socket::INET;
use Safe;
Line 1,192:
} else {
send_data('some_host', { a=>100, b=>[1 .. 10] });
}</
=={{header|Phix}}==
Line 1,198:
There is also a server/client/broker example.
Obviously you can trivially serialize() and deserialize() any Phix data to and from a string.
<!--<
<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>
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_term</span><span style="color: #0000FF;">(</span><span style="color: #000000;">context</span><span style="color: #0000FF;">)</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>
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_term</span><span style="color: #0000FF;">(</span><span style="color: #000000;">context</span><span style="color: #0000FF;">)</span>
<!--</
=={{header|PicoLisp}}==
===Server===
<
(let? Sock (accept @)
(unless (fork) # Handle request in child process
Line 1,272:
(pr (eval @)) ) ) ) # Evaluate and send reply
(bye) ) # Exit child process
(close Sock) ) ) # Close socket in parent process</
===Client===
<
(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</
Output:
<pre>PID 18372
Line 1,291:
==== Server ====
<
# -*- coding: utf-8 -*-
Line 1,328:
except KeyboardInterrupt:
print 'Exiting...'
server.server_close()</
==== Client ====
<
# -*- coding: utf-8 -*-
Line 1,353:
# control if foo_function returns True
if rpc.foo_function():
print 'Server says: foo_function returned True'</
===HTTP===
Line 1,359:
==== Server ====
<
# -*- coding: utf-8 -*-
Line 1,388:
except KeyboardInterrupt:
print 'Exiting...'
server.server_close()</
==== Client ====
<
# -*- coding: utf-8 -*-
Line 1,405:
print 'Server Status: %d' % response.status
print 'Server Message: %s' % response.read()</
===Socket, Pickle format===
Line 1,414:
==== Server ====
<
# -*- coding: utf-8 -*-
Line 1,471:
print 'Exiting...'
rpcserver.server_close()
</syntaxhighlight>
==== Client ====
<
# -*- coding: utf-8 -*-
Line 1,528:
print '42/2 is:', rpcclient.div(divisor=2, dividend=42)
rpcclient._close()
del rpcclient</
===Pyro===
Line 1,534:
==== Server ====
<
# -*- coding: utf-8 -*-
Line 1,559:
except KeyboardInterrupt:
print 'Exiting...'
server.shutdown()</
==== Client ====
<
# -*- coding: utf-8 -*-
Line 1,578:
print 'We sent two numbers to divide: %d and %d' % (NUM1, NUM2)
print 'Server responded the result: %s' % math.div(NUM1, NUM2)</
=== Spread ===
Line 1,589:
==== Client (Listener) ====
<
# -*- coding: utf-8 -*-
Line 1,606:
if hasattr(recv, 'sender') and hasattr(recv, 'message'):
print 'Sender: %s' % recv.sender
print 'Message: %s' % recv.message</
==== Client (Sender) ====
<
# -*- coding: utf-8 -*-
Line 1,620:
conn.multicast(spread.RELIABLE_MESS, 'test', 'hello, this is message sent from python')
conn.disconnect()</
=={{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).
<
#lang racket/base
(require racket/place/distributed racket/place)
Line 1,650:
(printf "Results: ~s\n" (map *channel-get places))
(exit))))
</syntaxhighlight>
=={{header|Raku}}==
Line 1,661:
Usage:
server.p6 [--server=<Any>] [--port=<Any>]</pre>
<syntaxhighlight lang="raku"
use JSON::Fast ;
sub MAIN( :$server='0.0.0.0' , :$port=3333 ) {
Line 1,696:
}
}
}</
client.raku:
<pre>Usage:
Line 1,702:
client.raku [--server=<Any>] [--port=<Any>] get <topic>
client.raku [--server=<Any>] [--port=<Any>] dump</pre>
<syntaxhighlight lang="raku"
use JSON::Fast ;
multi MAIN('set', $topic, $message='', :$server='localhost', :$port='3333', :$json='') {
Line 1,730:
}
}
}</
examples:
<pre>echo '{"function":"set","topic":"push","message":["perl5","raku","rakudo"]}' | nc localhost 3333
Line 1,757:
'''Server'''
<
# The URI for the server to connect to
Line 1,777:
DRb.start_service(URI, FRONT_OBJECT)
# Wait for the drb server thread to finish before exiting.
DRb.thread.join</
'''Client'''
<
# The URI to connect to
Line 1,793:
timeserver = DRbObject.new_with_uri(SERVER_URI)
puts timeserver.get_current_time</
=={{header|Tcl}}==
A rudimentary IRC Server
<
global connections
set connections [dict create]
Line 1,859:
}
main</
Client
<
global argv argc
if {$argc != 2} {
Line 1,896:
}
main</
=={{header|UnixPipes}}==
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.}}
<
tail -f /tmp/buffer | nc -l 127.0.0.1 1234 | sh >/tmp/buffer 2>&1</
Limitations:
Line 1,914:
===Client===
<
Now you can enter commands in the client terminal and get the output back through the same connection.
Line 1,929:
<br>
We need two Wren scripts one for each VM:
<
class Rpc {
Line 1,948:
Rpc.handleHTTP()
var listener = Listener.listen("tcp", ":1234")
HTTP.serve(listener)</
<br>
<
class TaxComputer {
Line 1,957:
return amount * rate
}
}</
<br>
We now embed these scripts in the following Go program and run it on one terminal.
<
package main
Line 2,044:
vm.Free()
vm2.Free()
}</
<br>
'''Client:'''
<br>
Just one Wren script needed here:
<
import "./fmt" for Fmt
Line 2,064:
var tax = client.call("TaxComputer.Tax", amount)
Fmt.print("Tax on $0.2f = $0.2f", amount, tax)
}</
<br>
which we embed in the following Go program and run it on a different terminal.
<
package main
Line 2,122:
vm.InterpretFile(fileName)
vm.Free()
}</
{{out}}
|