[racket] RPC client/server (was: Limiting net-repl provided functions)

From: Jukka Tuominen (jukka.tuominen at finndesign.fi)
Date: Thu Jun 30 02:50:38 EDT 2011

To setup a RPC client/server system, I ended up tweaking Matthew's example
from "More: Systems Programming with Racket", now that I understood better
what was needed.


Below is the actual code, in case somebody else finds it useful (tested in
Linux env. only). To filter out illegal functions, I'll propably create a
list predicates and test them one by one against the rpc candidate. Overall,
this seems promising for building further Liitin proof-of-concepts. Please,
let me know if you find anything critical or a place for improvement in the

Once again, thank you everyone for all the help!!

br, jukka

|  J U K K A   T U O M I N E N
|  m a n a g i n g   d i r e c t o r  M. A.
|  Finndesign  Kauppiaankatu 13, FI-00160 Helsinki, Finland
|  mobile +358 50 5666290
|  jukka.tuominen at finndesign.fi  www.finndesign.fi

#lang racket


(define server-name "localhost")
(define server-port 9877)
(define max-allow-wait 20); max concurrent clients waiting for turn
(define reuse? #f)
(define time-limit 10); secs for each rpc request

(define (allowed? expr);; Filter out illegal requests here

(define (run-rpc-server)
  (define (accept-and-handle listener)
    (define cust (make-custodian))
    (custodian-limit-memory cust (* 50 1024 1024))
    (parameterize ((current-custodian cust))
      (define expr "")
      (define-values (client->me me->client) (tcp-accept listener))
      (thread (lambda ()
                (set! expr (read client->me))
                (if (allowed? expr)
                    (write (eval expr) me->client)
                    (error "Illegal procedure call!" me->client))
                (close-output-port me->client)
                (close-input-port client->me))))
    (thread (lambda () ;; Watcher thread
              (sleep time-limit)
              (custodian-shutdown-all cust))))
  (define main-cust (make-custodian))
  (parameterize ((current-custodian main-cust))
    (define listener (tcp-listen server-port max-allow-wait reuse? #f))
    (define (loop)
      (accept-and-handle listener)
    (thread loop))
  (lambda ()
    (custodian-shutdown-all main-cust)))


;(define server-name "localhost")
;(define server-port 9877)

(define (rpc server-name expr); using default port
  (let-values (((server->me me->server)
                (tcp-connect server-name server-port)))
    (write expr me->server)-
    (close-output-port me->server)
    (let ((response (read server->me)))
      (close-input-port server->me)



(rpc "localhost" '(+ 1 2 3))
(+ 5 (rpc "localhost" '(+ 1 2 3)) ); combine local with remote

Posted on the users mailing list.