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.