
/* dgram.q: connectionless server/client example using datagrams */

import system;

def BUFSZ = 500000; // buffer size

/* the server: receive messages, evaluate them as Q expressions, and send back
   the results */

def SERVER = ("localhost",5001); // the server address

server		= server_loop FD
		    where FD:Int = socket AF_INET SOCK_DGRAM 0,
		      () = bind FD SERVER;
		= perror "server" otherwise;

server_loop FD	= sendto FD 0 (ADDR,eval MSG) || server_loop FD
		    where (ADDR,MSG) = recvfrom FD 0 BUFSZ;
		= server_loop FD otherwise;

/* evaluate an expression encoded as a byte string, catch syntax errors and
   exceptions, convert result back to a byte string */

eval MSG	= catch exception (bytestr (str VAL))
		    where 'VAL = valq (bstr MSG);
		= bytestr ">>> SYNTAX ERROR" otherwise;
exception _	= bytestr ">>> ABORTED";

/* the client: read input from user, send it to the server, print returned
   result */

def CLIENT = ("localhost",5002); // the client address

client		= client_loop FD
		    where FD:Int = socket AF_INET SOCK_DGRAM 0,
		      () = bind FD CLIENT;
		= perror "client" otherwise;

client_loop FD	= sendto FD 0 (SERVER,bytestr MSG) ||
		  printf "%s\n" (bstr (recv FD 0 BUFSZ)) || client_loop FD
		    if not null MSG
		    where MSG:String = writes "\nclient> " || flush || reads;
		= () otherwise;
