Distributed programming: Difference between revisions

From Rosetta Code
Content added Content deleted
(language tags (what happened here?))
(The reason that UnderBot tagged every example as AutoHotkey is that all the headers except AutoHotkey's were formatted like =this= instead of like ==this==. I fixed the formatting.)
Line 6: Line 6:
See [[Distributed program/AutoHotkey]].
See [[Distributed program/AutoHotkey]].


={{Header|C}}=
=={{header|C}}==
{{works with|Win32}} (Visual C/C++ 6.0)
{{works with|Win32}} (Visual C/C++ 6.0)


Line 275: Line 275:
}</lang>
}</lang>


={{header|D}}=
=={{header|D}}==

==Socket==
{{works with|Tango}}
{{works with|Tango}}
=== Server ===
=== Server ===
Line 343: Line 343:
}</lang>
}</lang>


={{header|E}}=
=={{header|E}}==
'''Protocol:''' Pluribus
'''Protocol:''' Pluribus


Line 393: Line 393:
}</lang>
}</lang>


={{header|Erlang}}=
=={{header|Erlang}}==
The protocol is erlang's own
The protocol is erlang's own
=== Server ===
=== Server ===
Line 451: Line 451:




={{header|Objective-C}}=
=={{header|Objective-C}}==
Distributed Objects are ''natural'' to Objective-C, and OpenStep and derivated framework offers an easy way of ''using'' remote objects as if it were local. The client must only know the protocol the remote object support. For the rest, calling a remote object's method or local object's method is transparent.
Distributed Objects are ''natural'' to Objective-C, and OpenStep and derivated framework offers an easy way of ''using'' remote objects as if it were local. The client must only know the protocol the remote object support. For the rest, calling a remote object's method or local object's method is transparent.


Line 574: Line 574:
}</lang>
}</lang>


={{header|OCaml}}=
=={{header|OCaml}}==
{{works with|JoCaml}}
{{works with|JoCaml}}


Line 628: Line 628:
find "foo"</lang>
find "foo"</lang>


={{header|Oz}}=
=={{header|Oz}}==
We show a programm that starts a server on a remote machine, exchanges two messages with that server and finally shuts it down.
We show a programm that starts a server on a remote machine, exchanges two messages with that server and finally shuts it down.


Line 672: Line 672:
{RM close}</lang>
{RM close}</lang>


={{header|Python}}=
=={{header|Python}}==
{{works with|Python|2.4 and 2.6}}
{{works with|Python|2.4 and 2.6}}

==XML-RPC==
=== XML-RPC ===
'''Protocol:''' XML-RPC
'''Protocol:''' XML-RPC


=== Server ===
==== Server ====
<lang python>#!/usr/bin/env python
<lang python>#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
Line 717: Line 718:
server.server_close()</lang>
server.server_close()</lang>


=== Client ===
==== Client ====
<lang python>#!/usr/bin/env python
<lang python>#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
Line 742: Line 743:
print 'Server says: foo_function returned True'</lang>
print 'Server says: foo_function returned True'</lang>


==HTTP==
===HTTP===
'''Protocol:''' HTTP
'''Protocol:''' HTTP


=== Server ===
==== Server ====
<lang python>#!/usr/bin/python
<lang python>#!/usr/bin/python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
Line 777: Line 778:
server.server_close()</lang>
server.server_close()</lang>


=== Client ===
==== Client ====
<lang python>#!/usr/bin/python
<lang python>#!/usr/bin/python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
Line 794: Line 795:
print 'Server Message: %s' % response.read()</lang>
print 'Server Message: %s' % response.read()</lang>


==Socket, Plain Text==
===Socket, Plain Text===
'''Protocol:''' Plain Text
'''Protocol:''' Plain Text


=== Server ===
==== Server ====
<lang python>#!/usr/bin/python
<lang python>#!/usr/bin/python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
Line 823: Line 824:
tcpserver.server_close()</lang>
tcpserver.server_close()</lang>


=== Client ===
==== Client ====
<lang python>#!/usr/bin/python
<lang python>#!/usr/bin/python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
Line 847: Line 848:




==Pyro==
===Pyro===
'''Note:''' You should install Pyro (http://pyro.sourceforge.net) first and run '''pyro-ns''' binary to run code below.
'''Note:''' You should install Pyro (http://pyro.sourceforge.net) first and run '''pyro-ns''' binary to run code below.


=== Server ===
==== Server ====
<lang python>#!/usr/bin/python
<lang python>#!/usr/bin/python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
Line 878: Line 879:
server.shutdown()</lang>
server.shutdown()</lang>


=== Client ===
==== Client ====
<lang python>#!/usr/bin/python
<lang python>#!/usr/bin/python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
Line 897: Line 898:
print 'Server responded the result: %s' % math.div(NUM1, NUM2)</lang>
print 'Server responded the result: %s' % math.div(NUM1, NUM2)</lang>


== Spread ==
=== Spread ===
'''Note:''' You should install Spread (http://www.spread.org) and its python bindings (http://www.python.org/other/spread/)
'''Note:''' You should install Spread (http://www.spread.org) and its python bindings (http://www.python.org/other/spread/)


=== Server ===
==== Server ====
You don't need any code for server. You should start "spread" daemon by typing "spread -c /etc/spread.conf -n localhost". If you want more configuration, look at /etc/spread.conf.
You don't need any code for server. You should start "spread" daemon by typing "spread -c /etc/spread.conf -n localhost". If you want more configuration, look at /etc/spread.conf.


After starting daemon, if you want to make sure that it is running, enter '''spuser -s 4803''' command where 4803 is your port set in spread.conf, you will see prompt, type '''j user''', you should see something like this message: ''Received REGULAR membership for group test with 3 members, where I am member 2''
After starting daemon, if you want to make sure that it is running, enter '''spuser -s 4803''' command where 4803 is your port set in spread.conf, you will see prompt, type '''j user''', you should see something like this message: ''Received REGULAR membership for group test with 3 members, where I am member 2''


=== Client (Listener) ===
==== Client (Listener) ====
<lang python>#!/usr/bin/python
<lang python>#!/usr/bin/python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
Line 925: Line 926:
print 'Message: %s' % recv.message</lang>
print 'Message: %s' % recv.message</lang>


=== Client (Sender) ===
==== Client (Sender) ====
<lang python>#!/usr/bin/python
<lang python>#!/usr/bin/python
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
Line 939: Line 940:
conn.disconnect()</lang>
conn.disconnect()</lang>


={{header|Ruby}}=
=={{header|Ruby}}==
Uses {{libheader|dRuby}}
Uses {{libheader|dRuby}}
The "druby:" protocol uses TCP/IP sockets for communication.
The "druby:" protocol uses TCP/IP sockets for communication.
Line 982: Line 983:
puts timeserver.get_current_time</lang>
puts timeserver.get_current_time</lang>


={{header|Tcl}}=
=={{header|Tcl}}==
A rudimentary IRC Server
A rudimentary IRC Server
<lang tcl>proc main {} {
<lang tcl>proc main {} {
Line 1,085: Line 1,086:
main</lang>
main</lang>


={{header|UnixPipes}}=
=={{header|UnixPipes}}==
Uses netcat
Uses netcat


server
server
(echo 1; echo 2; echo 3) | nc -l 1024
<lang bash>(echo 1; echo 2; echo 3) | nc -l 1024</lang>


client
client
nc 192.168.0.1 1024 | wc -l
<lang bash>nc 192.168.0.1 1024 | wc -l</lang>

Revision as of 15:52, 17 January 2010

Task
Distributed programming
You are encouraged to solve this task according to the task description, using any language you may know.

Given two computers on a network, send messages between them. The protocol used may be language-specific or not, and should be suitable for general distributed programming.

AutoHotkey

See Distributed program/AutoHotkey.

C

Works with: Win32

(Visual C/C++ 6.0)

The changes needed to work with Linux/Unix should be small. The example server serves only one client at a time. The protocol has 3 messages. The first character determines the server action.

'0' - echo string reversed '1' - echo string '2' - shutdown the server.

Server

<lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include <winsock.h>

//#include <sys/socket.h> //#include <inet.h>

  1. include <string.h>

//#include <time.h>

  1. include <windows.h>
  2. pragma comment(lib, "wsock32.lib")

typedef struct sockaddr_in * InetSockAddr;

typedef int (*Handler)( InetSockAddr client, int socket );

typedef struct sServer {

   Handler	handler;
   int		running;
   int		sock;
   struct sockaddr_in addr;

} *Server;

Server NewServer( short port, Handler handler) {

   int sock;
   struct sockaddr_in svrAddr;
   Server srv= (Server)malloc(sizeof(struct sServer));
   if (!srv) return srv;
   srv->handler = handler;
   srv->running = 1;
   sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
   if (sock <0 ) {
       printf("Couldn't open socket. -failed %d \n", sock);
       exit(1);
   }
   srv->sock = sock;
   memset(&svrAddr, 0, sizeof(struct sockaddr_in));
   svrAddr.sin_family = AF_INET;
   svrAddr.sin_addr.s_addr = htonl(INADDR_ANY);  //any incoming addr ok
   svrAddr.sin_port = htons(port);
   srv->addr = svrAddr;
   if (bind(sock, (struct sockaddr *)&svrAddr, sizeof(svrAddr)) <0) {
       printf("Bind to port %d failed\n", port);
       exit(1);
       }
   return srv;

}

  1. define MAXPENDING SOMAXCONN
  2. define close(sock) closesocket(sock)

int ServerServe( Server svr) {

   struct sockaddr_in cli_addr;
   int clen = sizeof(cli_addr);
   if (listen(svr->sock, MAXPENDING) < 0) {
       printf("listen() call failed.\n");
       return -1;
   }
   while (svr->running) {
       int sock = accept(svr->sock, (struct sockaddr *) &cli_addr, &clen);
       if (sock < 0) {
           printf("accept call failed in ServerServ.\n");
           svr->running = 0;
       }
       else 
           svr->running = (*(svr->handler))( &cli_addr, sock );
   }

}

  1. define ServerDelete( svr ) \
   { if(svr->sock>0) close(svr->sock); \
   free(svr); svr = NULL; }
  1. define BUFR_SIZE 256

/* - return 0 on success, nonzero on done; */ int SimpleHandler( InetSockAddr cli_addr, int cli_sock ) {

   char msgBufr[BUFR_SIZE];
   int  msgSize;
   int  rplySize;
   char *rplyMsg;
   int mcode;
   do {
       msgSize = recv(cli_sock, msgBufr, sizeof(msgBufr), 0) ;
       if (msgSize < 0) {
           printf("done receiving\n");
           return 1;
       }
       mcode = msgBufr[0];
       switch(mcode) {
       default:
       case '0': {
             char *p1 = msgBufr+1;
             char *p2 = msgBufr+msgSize-2;
             while (p2>p1) {
                 *p1 = *p1 + *p2; *p2 = *p1 - *p2; *p1 = *p1 - *p2;
                 p1++; p2--;
             }
             rplyMsg = msgBufr;
           }
           break;
       case '1':
           rplyMsg = msgBufr;
           break;
       case '2':
           rplyMsg = "Server Quitting";
           // server should quit
           break;
       }
       rplySize = strlen(rplyMsg)+1;
       if (rplySize > 0) {
           int bytesSent =  send(cli_sock, rplyMsg, rplySize, 0);
           if (bytesSent < rplySize)  {
               printf("Not All bytes sent back from msg.");
               msgSize = 0;
           }
       }
   } while ((msgSize > 0) && (mcode !=2));
   return (mcode == 2);	// true if server should quit

}

int main( int argc, char *argv[]) {

   short port;
   Server server;
   WORD  sockVrsn;
   WSADATA  wsaData;
   sockVrsn = MAKEWORD(1,1);
   if (argc < 2) {
       printf("Usage %s <port number>\n",argv[0]);
       exit(1);
   }
   WSAStartup(sockVrsn, &wsaData);
   port = (short)atoi(argv[1]);
   server = NewServer( port, &SimpleHandler);
   if (server){
       ServerServe(server);
       ServerDelete(server);
   }
   return 0;

}</lang>

Client

<lang c>#include <stdio.h>

  1. include <stdlib.h>
  2. include <winsock.h>

//#include <sys/socket.h> //#include <inet.h>

  1. include <string.h>

//#include <time.h>

  1. include <windows.h>
  2. pragma comment(lib, "wsock32.lib")

typedef struct sockaddr_in * InetSockAddr;

typedef struct sClient {

   int		sock;
   struct sockaddr_in addr;

} *Client;

Client NewClient( char *ipAddr, short port ) {

   int sock;
   struct sockaddr_in svrAddr;
   Client clint= (Client)malloc(sizeof(struct sClient));
   if (!clint) return clint;
   sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
   if (sock <0 ) {
       printf("Couldn't open socket. -failed %d \n", sock);
       exit(1);
   }
   clint->sock = sock;
   memset(&svrAddr, 0, sizeof(struct sockaddr_in));
   svrAddr.sin_family = AF_INET;
   svrAddr.sin_addr.s_addr = inet_addr(ipAddr);  
   printf("IP addr: %x", inet_addr(ipAddr));
   svrAddr.sin_port = htons(port);
   clint->addr = svrAddr;
   if (connect(sock, (struct sockaddr *)&svrAddr, sizeof(svrAddr)) <0) {
       perror("connect failed");
       printf("Connect to Server %s:%d failed\n", ipAddr,port);
       exit(1);
       }
   return clint;

}

  1. define close(sock) closesocket(sock)
  1. define BUFR_SIZE 128

int ClientDoProcs( Client clint, char *mlist[]) {

   char rcvBufr[BUFR_SIZE];
   char **msg;
   int v;
   for (msg = mlist; *msg; msg++) {
       int mlen = strlen(*msg)+1;
       printf("Send: %s\n", *msg);
       v = send(clint->sock, *msg, mlen, 0);
       if (v != mlen ) {
           printf("MessageSend error: %d %d\n", v,mlen);
       }
       else {
           int bytesRcvd = 0;
           bytesRcvd = recv( clint->sock, rcvBufr, BUFR_SIZE-1, 0);
           if (bytesRcvd < 0) {
               printf("Error Rcvg Bytes\n");
               break;
           }
           printf("Recvd: %s\n", rcvBufr);
       }
   }
   return 0;

}

  1. define ClientDelete( cli ) \
   { if(cli->sock>0) close(cli->sock); \
   free(cli); cli = NULL; }

char *msglist[] = {

   "0Hello World!!!",
   "1Hello Teacher!",
   "1This should echo back same",
   "0This should echo back reversed",
   "2 ByeBye",
   NULL };

int main( int argc, char *argv[]) {

   short port;
   Client clint;
   WORD  sockVrsn;
   WSADATA  wsaData;
   sockVrsn = MAKEWORD(1,1);
   WSAStartup(sockVrsn, &wsaData);
   if (argc < 3) {
       printf("Usage %s <serverIP> <port number>\n",argv[0]);
       exit(1);
   }
   port = (short)atoi(argv[2]);
   // argv[1]="127.0.0.1";
   clint = NewClient( argv[1], port );
   if (clint) {
       ClientDoProcs(clint, msglist);
       ClientDelete(clint);
   }
   Sleep(10);
   return 0;

}</lang>

D

Works with: Tango

Server

<lang D>module distributedserver ; import tango.net.ServerSocket, tango.text.convert.Integer,

      tango.text.Util, tango.io.Stdout ;

void main() {

 auto Ip = new InternetAddress("localhost", 12345) ;    
 auto server = new ServerSocket(Ip) ;
 auto socket = server.accept ;     
 auto buffer = new char[socket.bufferSize] ;
 bool quit = false ;
 
 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 ;     
 } 
 if(socket) socket.close ;

}</lang>

Client

<lang D>module distributedclient ; import tango.net.SocketConduit, tango.net.InternetAddress,

      tango.text.Util, tango.io.Stdout ;

void main(char[][] args) {

 if(args.length> 1) {
   try {
     auto Ip = new InternetAddress("localhost", 12345) ;    
     auto socket = new SocketConduit ;     
     socket.connect(Ip) ;
     auto buffer = new char[socket.bufferSize] ;
 
     socket.output.write(join(args[1..$]," ")) ;
     auto len = socket.input.read(buffer) ;    
     if(len > 0) Stdout(buffer[0..len]).newline ;
   
     if(socket) socket.close ;
   } catch(Exception e) 
     Stdout(e.msg).newline ;
 } else
   Stdout("usage: supply argument as,\n\tquit\n"
     "\tsquare <number>\n\tadd <number> <number>").newline ;

}</lang>

E

Protocol: Pluribus

This service cannot be used except by clients which know the URL designating it, messages are encrypted, and the client authenticates the server. However, it is vulnerable to denial-of-service by any client knowing the URL.

Server

(The protocol is symmetric; this program is the server only in that it is the one which is started first and exports an object.)

<lang E>def storage := [].diverge()

def logService {

 to log(line :String) {
   storage.push([timer.now(), line])
 }
 to search(substring :String) {
   var matches := []
   for [time, line] ? (line.startOf(substring) != -1) in storage {
     matches with= [time, line]
   }
   return matches
 }

}

introducer.onTheAir() def sturdyRef := makeSturdyRef.temp(logService) println(<captp>.sturdyToURI(sturdyRef)) interp.blockAtTop()</lang>

This will print the URL of the service and run it until aborted.

Client

The URL provided by the server is given as the argument to this program.

<lang E>def [uri] := interp.getArgs() introducer.onTheAir() def sturdyRef := <captp>.sturdyFromURI(uri) def logService := sturdyRef.getRcvr()

logService <- log("foot") logService <- log("shoe")

println("Searching...") when (def result := logService <- search("foo")) -> {

 for [time, line] in result {
   println(`At $time: $line`)
 }

}</lang>

Erlang

The protocol is erlang's own

Server

srv.erl

<lang erlang>-module(srv). -export([start/0, wait/0]).

start() ->

  net_kernel:start([srv,shortnames]),
  erlang:set_cookie(node(), rosetta),
  Pid = spawn(srv,wait,[]),
  register(srv,Pid),
  io:fwrite("~p ready~n",[node(Pid)]),
  ok.

wait() ->

  receive
      {echo, Pid, Any} ->
          io:fwrite("-> ~p from ~p~n", [Any, node(Pid)]),
          Pid ! {hello, Any},
          wait();
      Any -> io:fwrite("Error ~p~n", [Any])
  end.</lang>

Client

client.erl

<lang erlang>-module(client). -export([start/0, wait/0]).

start() ->

  net_kernel:start([client,shortnames]),
  erlang:set_cookie(node(), rosetta),
  {ok,Srv} = init:get_argument(server),
  io:fwrite("conencting to ~p~n", [Srv]),
  {srv, list_to_atom(Srv)} ! {echo,self(), hi},
  wait(),
  ok.

wait() ->

  receive
      {hello, Any} -> io:fwrite("Received ~p~n", [Any]);
      Any -> io:fwrite("Error ~p~n", [Any])
  end.</lang>

running it (*comes later)

|erlc srv.erl
|erl -run srv start -noshell
 srv@agneyam ready
*-> hi from client@agneyam
|erlc client.erl
|erl -run client start -run init stop -noshell -server srv@agneyam
 conencting to "srv@agneyam"
 Received hi


Objective-C

Distributed Objects are natural to Objective-C, and OpenStep and derivated framework offers an easy way of using remote objects as if it were local. The client must only know the protocol the remote object support. For the rest, calling a remote object's method or local object's method is transparent.

Works with: GNUstep

Server

The server vending the object with the name DistributedAction

ActionObjectProtocol.h <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</lang>

ActionObject.h <lang objc>#import <Foundation/Foundation.h>

  1. import "ActionObjectProtocol.h"

@interface ActionObject : NSObject <ActionObjectProtocol>

 // we do not have much for this example!

@end</lang>

ActionObject.m <lang objc>#import <Foundation/Foundation.h>

  1. import "ActionObject.h"

@implementation ActionObject -(NSString *)sendMessage: (NSString *)msg {

 NSLog(@"client sending message %@", msg);
 return @"server answers ...";

} @end</lang>

server.m <lang objc>#import <Foundation/Foundation.h>

  1. import "ActionObject.h"

int main (void) {

 NSAutoreleasePool *pool;
 ActionObject *action;
 NSConnection *connect;
 NSSocketPort *port;
 
 pool = [[NSAutoreleasePool alloc] init];
 
 action = [[ActionObject alloc] init];
 port = (NSSocketPort *)[NSSocketPort port];
 // initWithTCPPort: 1234 and other methods are not supported yet
 // by GNUstep
 connect = [NSConnection 

connectionWithReceivePort: port sendPort: port]; // or sendPort: nil

 [connect setRootObject: action];
 /* "vend" the object ActionObject as DistributedAction; on GNUstep
    the Name Server that allows the resolution of the registered name
    is bound to port 538 */
 if ([connect registerName:@"DistributedAction"

withNameServer: [NSSocketPortNameServer sharedInstance] ] == NO)

 {
   NSLog(@"can't register the server DistributedAction");
   exit(EXIT_FAILURE);
 }
 
 NSLog(@"waiting for messages...");
 [[NSRunLoop currentRunLoop] run];
 [pool release];
 return 0;

}</lang>

Client

client.m <lang objc>#import <Foundation/Foundation.h>

  1. import "ActionObjectProtocol.h"

int main(void) {

 NSAutoreleasePool *pool;
 NSArray *args;
 id <ActionObjectProtocol> action;
 NSString *msg, *backmsg;
 pool = [[NSAutoreleasePool alloc] init];
 action = (id <ActionObjectProtocol>)
   [NSConnection
     rootProxyForConnectionWithRegisteredName: @"DistributedAction" 
     host: @"localhost"
     usingNameServer: [NSSocketPortNameServer sharedInstance] ];
 if (action == nil)
 {
   NSLog(@"can't connect to the server");
   exit(EXIT_FAILURE);
 }
 
 args = [[NSProcessInfo processInfo] arguments];
 if ([args count] == 1)
 {
   NSLog(@"specify a message");
   exit(EXIT_FAILURE);
 }
 
 msg = [args objectAtIndex: 1];
 // "send" (call the selector "sendMessage:" of the (remote) object
 // action) the first argument's text as msg, store the message "sent
 // back" and then show it in the log
 backmsg = [action sendMessage: msg];
 NSLog(backmsg);
 [pool release];
 return 0;

}</lang>

OCaml

Works with: JoCaml

Minimalistic distributed logger with synchronous channels using the join calculus on top of OCaml.

Server

<lang ocaml>open Printf

let create_logger () =

 def log(text) & logs(l) =
     printf "Logged: %s\n%!" text;
     logs((text, Unix.gettimeofday ())::l) & reply to log
  or search(text) & logs(l) =
     logs(l) & reply List.filter (fun (line, _) -> line = text) l to search
 in
   spawn logs([]);
   (log, search)

def wait() & finished() = reply to wait

let register name service = Join.Ns.register Join.Ns.here name service

let () =

 let log, search = create_logger () in
   register "log" log;
   register "search" search;
   Join.Site.listen (Unix.ADDR_INET (Join.Site.get_local_addr(), 12345));
   wait ()</lang>

Client

<lang ocaml>open Printf

let ns_there = Join.Ns.there (Unix.ADDR_INET (Join.Site.get_local_addr(), 12345))

let lookup name = Join.Ns.lookup ns_there name

let log : string -> unit = lookup "log" let search : string -> (string * float) list = lookup "search"

let find txt =

 printf "Looking for %s...\n" txt;
 List.iter (fun (line, time) ->
              printf "Found: '%s' at t = %f\n%!" (String.escaped line) time)
   (search txt)

let () =

 log "bar";
 find "foo";
 log "foo";
 log "shoe";
 find "foo"</lang>

Oz

We show a programm that starts a server on a remote machine, exchanges two messages with that server and finally shuts it down.

<lang oz>declare

 functor ServerCode
 export
    port:Prt
 define
    Stream
    Prt = {NewPort ?Stream}
    thread

for Request#Reply in Stream do case Request of echo(Data) then Reply = Data [] compute(Function) then Reply = {Function} end end

    end
 end
 %% create the server on some machine
 %% (just change "localhost" to some machine
 %% that you can use with a passwordless rsh login
 %% and that has the same Mozart version installed)
 RM = {New Remote.manager init(host:localhost)}
 %% execute the code encapsulated in the ServerCode functor
 Server = {RM apply(ServerCode $)}
 %% Shortcut: send a message to Server and receive a reply
 fun {Send X}
    {Port.sendRecv Server.port X}
 end

in

 %% echo
 {System.showInfo "Echo reply: "#{Send echo(hello)}}
 %% compute
 {System.showInfo "Result of computation: "#
  {Send compute(fun {$} 8 div 4 end)}}
 %% shut down server
 {RM close}</lang>

Python

Works with: Python version 2.4 and 2.6

XML-RPC

Protocol: XML-RPC

Server

<lang python>#!/usr/bin/env python

  1. -*- coding: utf-8 -*-

import SimpleXMLRPCServer

class MyHandlerInstance:

   def echo(self, data):
       Method for returning data got from client
       return 'Server responded: %s' % data
   def div(self, num1, num2):
       Method for divide 2 numbers
       return num1/num2

def foo_function():

   A function (not an instance method)
   return True

HOST = "localhost" PORT = 8000

server = SimpleXMLRPCServer.SimpleXMLRPCServer((HOST, PORT))

  1. register built-in system.* functions.

server.register_introspection_functions()

  1. register our instance

server.register_instance(MyHandlerInstance())

  1. register our function as well

server.register_function(foo_function)

try:

   # serve forever
   server.serve_forever()

except KeyboardInterrupt:

   print 'Exiting...'
   server.server_close()</lang>

Client

<lang python>#!/usr/bin/env python

  1. -*- coding: utf-8 -*-

import xmlrpclib

HOST = "localhost" PORT = 8000

rpc = xmlrpclib.ServerProxy("http://%s:%d" % (HOST, PORT))

  1. print what functions does server support

print 'Server supports these functions:', print ' '.join(rpc.system.listMethods())

  1. echo something

rpc.echo("We sent this data to server")

  1. div numbers

print 'Server says: 8 / 4 is: %d' % rpc.div(8, 4)

  1. control if foo_function returns True

if rpc.foo_function():

   print 'Server says: foo_function returned True'</lang>

HTTP

Protocol: HTTP

Server

<lang python>#!/usr/bin/python

  1. -*- coding: utf-8 -*-

import BaseHTTPServer

HOST = "localhost" PORT = 8000

  1. we just want to write own class, we replace do_GET method. This could be extended, I just added basics
  2. see; http://docs.python.org/lib/module-BaseHTTPServer.html

class MyHTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler):

   def do_GET(self):
       # send 200 (OK) message
       self.send_response(200)
       # send header
       self.send_header("Content-type", "text/html")
       self.end_headers()
       # send context
       self.wfile.write("<html><head><title>Our Web Title</title></head>")

self.wfile.write("<body>

This is our body. You wanted to visit %s page

</body>" % self.path)

       self.wfile.write("</html>")

if __name__ == '__main__':

   server = BaseHTTPServer.HTTPServer((HOST, PORT), MyHTTPHandler)
   try:
       server.serve_forever()
   except KeyboardInterrupt:
       print 'Exiting...'
       server.server_close()</lang>

Client

<lang python>#!/usr/bin/python

  1. -*- coding: utf-8 -*-

import httplib

HOST = "localhost" PORT = 8000

conn = httplib.HTTPConnection(HOST, PORT) conn.request("GET", "/somefile")

response = conn.getresponse() print 'Server Status: %d' % response.status

print 'Server Message: %s' % response.read()</lang>

Socket, Plain Text

Protocol: Plain Text

Server

<lang python>#!/usr/bin/python

  1. -*- coding: utf-8 -*-

import SocketServer

HOST = "localhost" PORT = 8000

  1. our instance that will upper whatever it gets and send back to client

class UpperCaseHandler(SocketServer.StreamRequestHandler):

   def handle(self):
       print '%s connected' % self.client_address[0]
       # get what client sends
       get = self.rfile.readline()
       # write back to client
       self.wfile.write(get.upper())

if __name__ == '__main__':

   tcpserver = SocketServer.TCPServer((HOST, PORT), UpperCaseHandler)
   try:
       tcpserver.serve_forever()
   except KeyboardInterrupt:
       print 'Exiting...'
       tcpserver.server_close()</lang>

Client

<lang python>#!/usr/bin/python

  1. -*- coding: utf-8 -*-

import socket

HOST = "localhost" PORT = 8000

DATA = "my name is eren"

  1. connect to server and send data

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((HOST, PORT)) sock.send("%s\n" % DATA)

  1. get

response = sock.recv(256) sock.close()

print "We sent: %s" % DATA print 'Server responded: %s' % response</lang>


Pyro

Note: You should install Pyro (http://pyro.sourceforge.net) first and run pyro-ns binary to run code below.

Server

<lang python>#!/usr/bin/python

  1. -*- coding: utf-8 -*-

import Pyro.core import Pyro.naming

  1. create instance that will return upper case

class StringInstance(Pyro.core.ObjBase):

   def makeUpper(self, data):
       return data.upper()

class MathInstance(Pyro.core.ObjBase):

   def div(self, num1, num2):
       return num1/num2

if __name__ == '__main__':

   server = Pyro.core.Daemon()
   name_server = Pyro.naming.NameServerLocator().getNS()
   server.useNameServer(name_server)
   server.connect(StringInstance(), 'string')
   server.connect(MathInstance(), 'math')
   try:
       server.requestLoop()
   except KeyboardInterrupt:
       print 'Exiting...'
       server.shutdown()</lang>

Client

<lang python>#!/usr/bin/python

  1. -*- coding: utf-8 -*-

import Pyro.core

DATA = "my name is eren" NUM1 = 10 NUM2 = 5

string = Pyro.core.getProxyForURI("PYRONAME://string") math = Pyro.core.getProxyForURI("PYRONAME://math")

print 'We sent: %s' % DATA print 'Server responded: %s\n' % string.makeUpper(DATA)

print 'We sent two numbers to divide: %d and %d' % (NUM1, NUM2) print 'Server responded the result: %s' % math.div(NUM1, NUM2)</lang>

Spread

Note: You should install Spread (http://www.spread.org) and its python bindings (http://www.python.org/other/spread/)

Server

You don't need any code for server. You should start "spread" daemon by typing "spread -c /etc/spread.conf -n localhost". If you want more configuration, look at /etc/spread.conf.

After starting daemon, if you want to make sure that it is running, enter spuser -s 4803 command where 4803 is your port set in spread.conf, you will see prompt, type j user, you should see something like this message: Received REGULAR membership for group test with 3 members, where I am member 2

Client (Listener)

<lang python>#!/usr/bin/python

  1. -*- coding: utf-8 -*-

import spread

PORT = '4803'

  1. connect spread daemon

conn = spread.connect(PORT)

  1. join the room

conn.join('test')

print 'Waiting for messages... If you want to stop this script, please stop spread daemon' while True:

   recv = conn.receive()
   if hasattr(recv, 'sender') and hasattr(recv, 'message'):
       print 'Sender: %s' % recv.sender
       print 'Message: %s' % recv.message</lang>

Client (Sender)

<lang python>#!/usr/bin/python

  1. -*- coding: utf-8 -*-

import spread

PORT = '4803'

conn = spread.connect(PORT) conn.join('test')

conn.multicast(spread.RELIABLE_MESS, 'test', 'hello, this is message sent from python') conn.disconnect()</lang>

Ruby

Uses

Library: dRuby

The "druby:" protocol uses TCP/IP sockets for communication.

Server <lang ruby>require 'drb/drb'

  1. The URI for the server to connect to

URI="druby://localhost:8787"

class TimeServer

 def get_current_time
   return Time.now
 end

end

  1. The object that handles requests on the server

FRONT_OBJECT = TimeServer.new

$SAFE = 1 # disable eval() and friends

DRb.start_service(URI, FRONT_OBJECT)

  1. Wait for the drb server thread to finish before exiting.

DRb.thread.join</lang>

Client <lang ruby>require 'drb/drb'

  1. The URI to connect to

SERVER_URI = "druby://localhost:8787"

  1. Start a local DRbServer to handle callbacks.
  2. Not necessary for this small example, but will be required
  3. as soon as we pass a non-marshallable object as an argument
  4. to a dRuby call.

DRb.start_service

timeserver = DRbObject.new_with_uri(SERVER_URI) puts timeserver.get_current_time</lang>

Tcl

A rudimentary IRC Server <lang tcl>proc main {} {

   global connections
   set connections [dict create]
   socket -server handleConnection 12345
   vwait dummyVar ;# enter the event loop

}

proc handleConnection {channel clientaddr clientport} {

   global connections
   dict set connections $channel address "$clientaddr:$clientport"
   fconfigure $channel -buffering line
   fileevent $channel readable [list handleMessage $channel]

}

proc handleMessage {channel} {

   global connections
   if {[gets $channel line] == -1} {
       disconnect $channel
   } else {
       if {[string index [string trimleft $line] 0] eq "/"} {
           set words [lassign [split [string trim $line]] command]
           handleCommand $command $words $channel
       } else {
           echo $line $channel
       }
   }

}

proc disconnect {channel} {

   global connections
   dict unset connections $channel
   fileevent $channel readable ""
   close $channel

}

proc handleCommand {command words channel} {

   global connections
   switch -exact -- [string tolower $command] {
       /nick {
           dict set connections $channel nick [lindex $words 0]
       }
       /quit {
           echo bye $channel
           disconnect $channel
       }
       default {
           puts $channel "\"$command\" not implemented"
       }
   }

}

proc echo {message senderchannel} {

   global connections
   foreach channel [dict keys $connections] {
       if {$channel ne $senderchannel} {
           set time [clock format [clock seconds] -format "%T"]
           set nick [dict get $connections $channel nick]
           puts $channel [format "\[%s\] %s: %s" $time $nick $message]
       }
   }

}

main</lang> Client <lang tcl>proc main {} {

   global argv argc
   if {$argc != 2} {
       error "usage: [info script] serveraddress serverport"
   }
   connect {*}$argv
   vwait dummyVar

}

proc connect {addr port} {

   global sock
   set sock [socket $addr $port]
   fconfigure $sock -buffering line
   fileevent $sock readable getFromServer
   fileevent stdin readable sendToServer

}

proc getFromServer {} {

   global sock
   if {[gets $sock line] == -1} {
       puts "disconnected..."
       exit
   } else {
       puts $line
   }

}

proc sendToServer {} {

   global sock
   set msg [string trim [gets stdin]]
   if {[string length $msg] > 0} {
       puts $sock $msg
   }

}

main</lang>

UnixPipes

Uses netcat

server <lang bash>(echo 1; echo 2; echo 3) | nc -l 1024</lang>

client <lang bash>nc 192.168.0.1 1024 | wc -l</lang>