Distributed programming: Difference between revisions

Rewritten D entry
(Rewritten D entry)
Line 290:
 
=={{header|D}}==
Uses the <b>rpc</b> library:
{{incorrect|D|The protocol used is not sufficiently general-purpose.}}
https://github.com/adamdruppe/misc-stuff-including-D-programming-language-web-stuff/blob/master/rpc.d
 
This library is not standard, so this code (by Adam D. Ruppe) could and should be rewritten using more standard means.
{{works with|Tango}}
<lang d>import arsd.rpc;
=== Server ===
<lang D>module distributedserver ;
import tango.net.ServerSocket, tango.text.convert.Integer,
tango.text.Util, tango.io.Stdout ;
 
struct S1 {
void main() {
int number;
auto Ip = new InternetAddress("localhost", 12345) ;
string name;
auto server = new ServerSocket(Ip) ;
}
auto socket = server.accept ;
auto buffer = new char[socket.bufferSize] ;
 
struct S2 {
bool quit = false ;
string name;
int number;
while(!quit) {
}
bool error = false ;
try {
auto len = socket.input.read(buffer) ;
auto cmd = (len > 0) ? delimit(buffer[0..len], " ") : [""] ;
Stdout(cmd).newline.flush ;
switch (cmd[0]) {
case "square":
socket.output.write(toString(toInt(cmd[1]) * toInt(cmd[1]))) ; break ;
case"add":
socket.output.write(toString(toInt(cmd[1]) + toInt(cmd[2]))) ; break ;
case "quit":
socket.output.write("Server Shut down") ;
quit = true ; break ;
default: error = true ;
}
} catch (Exception e)
error = true ;
if(error) socket.output.write("<Error>") ;
if(socket) socket.close ;
if(!quit) socket = server.accept ;
}
 
interface ExampleNetworkFunctions {
if(socket) socket.close ;
string sayHello(string name);
}</lang>
int add(in int a, in int b) const pure nothrow;
=== Client ===
S2 structTest(S1);
<lang D>module distributedclient ;
void die();
import tango.net.SocketConduit, tango.net.InternetAddress,
}
tango.text.Util, tango.io.Stdout ;
 
// The server must implement the interface.
void main(char[][] args) {
class ExampleServer : ExampleNetworkFunctions {
override string sayHello(string name) {
return "Hello, " ~ name;
}
 
override int add(in int a, in int b) const pure nothrow {
if(args.length> 1) {
try { return a + b;
}
auto Ip = new InternetAddress("localhost", 12345) ;
 
auto socket = new SocketConduit ;
override S2 socket.connectstructTest(IpS1 a) ;{
return S2(a.name, a.number);
auto buffer = new char[socket.bufferSize] ;
}
 
socket.output.write(join(args[1..$]," ")) ;
override void die() {
auto len = socket.input.read(buffer) ;
throw new Exception("death requested");
if(len > 0) Stdout(buffer[0..len]).newline ;
}
 
if(socket) socket.close ;
mixin NetworkServer!ExampleNetworkFunctions;
} catch(Exception e)
}
Stdout(e.msg).newline ;
 
} else
class Client {
Stdout("usage: supply argument as,\n\tquit\n"
mixin NetworkClient!ExampleNetworkFunctions;
"\tsquare <number>\n\tadd <number> <number>").newline ;
}
 
void main(in string[] args) {
import std.stdio;
 
if (args.length > 1) {
auto client = new Client("localhost", 5005);
// These work like the interface above, but instead of
// returning the value, they take callbacks for success (where
// the arg is the retval) and failure (the arg is the
// exception).
client.sayHello("whoa", (a) { writeln(a); }, null);
client.add(1,2, (a){ writeln(a); }, null);
client.add(10,20, (a){ writeln(a); }, null);
client.structTest(S1(20, "cool!"),
(a){ writeln(a.name, " -- ", a.number); },
null);
client.die(delegate(){ writeln("shouldn't happen"); },
delegate(a){ writeln(a); });
client.eventLoop;
} else {
auto server = new ExampleServer(5005);
server.eventLoop;
}
}</lang>