Date: Thu, 20 Jun 2013 04:39:58 +0200
Quote:
- Casual Game Development
Flash Socket Server in Lisp
http://blog.pettomato.com/?p=17
Text:
-
(in-package :common-user)
-
-
(require :sb-bsd-sockets)
-
-
(defpackage :myServer
-
(:use :common
-
:sb-thread
-
:sb-bsd-sockets
-
:sb-unix
-
:sb-ext)
-
(:export :run
-
:stop))
-
-
(in-package :myServer)
-
-
(defparameter *default-server-address* '(192 168 0 1)
-
"The default address on which instances of the server listen.")
-
-
(defparameter *default-server-port* 8007
-
"The default port on which instances of the server listen.")
-
-
(defparameter *default-server-backlog* 16
-
"The default number of simultaneous connections to the server.")
-
-
(defconstant +null+ (code-char 0)
-
"A null byte.")
-
-
(defun read-upto-null (stream char-array)
-
"Read everything from stream up until a null byte or EOF."
-
;; TODO: char-array was separated for efficiency, but now
-
;; this isn't very clean.
-
(do ((c (read-char stream nil nil) (read-char stream nil nil)))
-
((or (equal c +null+)
-
(equal c nil))
-
(if (equal c +null+) char-array nil))
-
(vector-push-extend c char-array)))
-
-
(defmethod handle-client ((socket inet-socket))
-
"Handle a client request."
-
(let ((client-stream (socket-make-stream socket :input t :output t :element-type 'character :buffering :full))
-
(s (make-array 1024 :fill-pointer 0 :adjustable t :element-type 'character)))
-
(do ((message (read-upto-null client-stream s) (read-upto-null client-stream s)))
-
((equal message nil)) ; Quit when the client closes the socket.
-
(cond
-
((equal message "<policy-file-request/>")
-
(write-line "sending policy file")
-
(format client-stream "<?xml version=\"1.0\"?><cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"~A\" /></cross-domain-policy>" *default-server-port*)
-
(write-char +null+ client-stream) ; terminate the response with a null byte
-
(finish-output client-stream))
-
(t
-
(write-line message)))
-
(setf (fill-pointer s) 0))) ; Reset our character array
-
(write-line "Closing client connection.")
-
(socket-close socket))
-
-
(defmacro with-socket (socket &body body)
-
"Create and close a socket around the body."
-
`(let ((,socket (make-instance 'inet-socket
-
:type :stream
-
:protocol :tcp)))
-
(unwind-protect (progn ,@body)
-
(socket-close ,socket))))
-
-
(defmethod run ()
-
"Run the server, listening on the specified port and dispatching
-
client requests."
-
(write-line "Starting server.")
-
(with-socket server-socket
-
(setf (sockopt-reuse-address server-socket) t)
-
(socket-bind server-socket *default-server-address* *default-server-port*)
-
(socket-listen server-socket *default-server-backlog*)
-
(do ((client-socket (socket-accept server-socket) (socket-accept server-socket))) ; ignore peer value
-
(nil) ; infinite loop
-
(write-line "New client")
-
(let ((client-socket client-socket))
-
(make-thread (lambda () (handle-client client-socket)) :name "handle-client")))))
-
-
(defun start ()
-
(setf myServer-thread (make-thread (lambda () (run)) :name "myServer")))
-
-
(defun stop ()
-
(let ((st myServer-thread))
-
(cond
-
((thread-alive-p st)
-
(write-line "Server stopped.")
-
(terminate-thread st))
-
(t
-
(write-line "Server is not running.")
-
nil))))
-
-
;; start the server
-
(start)
Here is another version of a socket server that you can use to catch your debug messages from a live swf. Python version here. This one is written in SBCL, which was compiled with threading enabled.
NOTE: I am new to Lisp. I have a feeling this script will be revised several times.
This code was built off of some example code by Patrick May. Dave Roberts, on the sbcl-help mailing list also gave me a few pointers.
This server probably doesn't need to be multithreaded if you are only using it to catch your debug output. I, however, plan to build some other servers off of this, so I am keeping it this way.
The necessary Actionscript to communicate with this server is the same as the Python version.
LISP
Via FeedShow.com