An asynchronous network server

An event-based echo server in Spark-Scheme:

(define server (create-server
                   (lambda (client)
                      (socket-send client (recv-all client)))))

(listen server 8080)

This is built on top of the reactor framework:

(import (net) (reactor))

(define (create-server on-client-request)
   (let ((server-socket (socket-acceptor)))
     (acceptor-on-client-read! server-socket
          (lambda (acceptor client-socket)
             (socket-non-blocking! client-socket #t)
             (on-client-request client-socket)))
     (acceptor-on-server-timeout! server-socket
         (lambda (acceptor) null))
     (acceptor-on-client-connect! server-socket
          (lambda (acceptor client-socket)
             (acceptor-add-watch acceptor 
                   (connection-socket client-socket) 'for-read)))
     server-socket))

(define (listen server-socket port)
   (acceptor-port! server-socket port)
   (acceptor-open server-socket #t (list 10 0))
   (let ((cb null))
     (set! cb (lambda () (acceptor-watch server-socket) (cb)))
     (thread cb)))

(define (recv-all socket)
   (let loop ((in (socket-recv socket 1024))
              (s (open-output-string)))
     (if (> (string-length in) 0)
       (begin
          (fprintf s "~a" in)
          (loop (socket-recv socket 1024) s))
       (get-output-string s))))

A client written in python to test the server:

import socket
import sys

HOST = '127.0.0.1'
PORT = 8080

try:
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error, msg:
  sys.stderr.write("[ERROR] %s\n" % msg[1])
  sys.exit(1)

try:
  sock.connect((HOST, PORT))
except socket.error, msg:
  sys.stderr.write("[ERROR] %s\n" % msg[1])
  sys.exit(2)

req = ""
req = req + sys.argv[1]
req = req + "\n"

sock.send(req)
string = sock.recv(len(req))
print len(string)
sock.close()

Though it need some tidying-up, the reactor framework can be used to write interesting network applications.