




 
start-up-server &key function announce service address nodelay keepalive process-name wait error => process , startup-condition
A function name.
An output stream, 
t
, 
nil
 or a function.
An integer, a string or 
nil
.
An integer, a string or 
nil
.
A generalized boolean.
A generalized boolean.
A symbol or expression.
A boolean.
A boolean.
The 
start-up-server
 function starts a TCP server. Use process-kill to kill the server, and open-tcp-stream to send messages from another client to the server.
The function argument provides the name of the function that processes connections. When a connection is made function is called with the connected socket handle, at which point you can make a stream using make-instance and communicate with the client. The server does not accept more connections until function returns, so normally it should create another light-weight process to handle the connection. However, the operating system typically provides a small queue of partially accepted connections, which prevents connection failure for new clients until the server is ready to accept more connections. If function is not specified the built-in Lisp listener server is used. See the examples section below.
If 
announce
 is a stream or 
t
 (denoting 
*standard-output*
), a message appears on the stream when the server is started. 
If 
announce
 is a function it is called when the server is started. 
announce
 should take two arguments: 
socket
 and 
condition
. 
socket
 is the socket used by the server: 
announce
 can therefore be used to record this socket. 
condition
 describes the error if there is one. 
announce
 can be called with 
socket
 
nil
 and a condition only if 
error
 is 
nil
. If the process is killed, 
announce
 is called with 
socket
 
nil
 and 
condition
 
nil
.
The default for 
announce
 is 
nil
, meaning there is no message. 
If 
service
 is a string or positive integer, it specifies the name of the service. The location of the file specifying the names of services available varies, but typically on Windows 98 it is called 
SERVICES
 and is stored in the 
Windows
 directory, and on Windows NT-based systems it is the file 
%SystemRoot%\system32\drivers\etc\SERVICES
If 
service
 is 
nil
 or 0, then 
start-up-server
 chooses a free port. The default value for 
service
 is "
lispworks
".
If 
address
 is a string or integer that can be resolved to an IP address, then the server only receives connections for that IP address. This must be one of the addresses associated with the machine and allowed values are a string naming a host, such as 
"www.nowhere.com"
, a string providing the IP address, such as 
"204.71.177.75"
, or and integer IP address in network order, such as 
#xCC47B14B
.
If 
address
 is 
nil
 or 0, then the server will receive connections to all IP addresses on the machine.  This is the default.
If 
keepalive
 is true, SO_KEEPALIVE is set on the socket. The default value of 
keepalive
 is 
nil
.
If 
nodelay
 is true, TCP_NODELAY is set on the socket. The default value of 
nodelay
 is 
t
.
The process-name specifies the process name. The default is constructed from the service name in the following fashion:
(format nil "~S server" service)
The 
wait
 argument controls whether 
start-up-server
 waits for the server to start or returns immediately. When 
wait
 is non-
nil
 and an error was signalled, 
process
 is 
nil
 and the error is returned in 
startup-condition
  Otherwise just one value, the server process, is returned. The default for 
wait
 is 
nil
.
The 
error
 argument controls what happens if an error is signalled in the server thread. If 
error
 is 
nil
 then the thread is terminated. If 
error
 is non-
nil
 then the debugger is entered. The default value for error is 
(not
 
wait
)
.
Note: some versions of Microsoft Windows fail to detect the case where more than one server binds a given port, so an error will not be raised in this situation.
The following example uses the built-in Lisp listener server:
(comm:start-up-server :service 10243)
It makes a Lisp listener server on port 10243 (check with local network managers that this port number is safe to use). When a client connects to this, Lisp calls 
read
. The client should send a string using Common Lisp syntax followed by a newline. This string is used to name a new light-weight process that runs a Lisp listener. When this has been created, the server waits for more connections.
The next example illustrates the use of the 
function
 argument. For each line of input read by the server it writes the line back with a message. The stream generates 
EOF
 if the other end closes the connection.
(defvar *talk-port* 10244)  ; a free TCP port number
(defun make-stream-and-talk (handle)
(let ((stream (make-instance 'comm:socket-stream
:socket handle
:direction :io
:element-type
'base-char)))
(mp:process-run-function (format nil "talk ~D"
handle)
'()
'talk-on-stream stream)))
(defun talk-on-stream (stream)
(unwind-protect
(loop for line = (read-line stream nil nil)
while line
do
(format stream "You sent: '~A'~%" line)
(force-output stream))
(close stream)))
(comm:start-up-server :function 'make-stream-and-talk
:service *talk-port*)
This is a client which uses the talk server:
(defun talking-to-myself ()
(with-open-stream
(talk (comm:open-tcp-stream "localhost"
*talk-port*))
(dolist (monolog
'("Hello self."
"Why don't you say something original?"
"Talk to you later then. Bye."))
(write-line monolog talk)
(force-output talk)
(format t "I said: \"~A\"~%"
monolog)
(format t "Self replied: \"~A\"~%"
(read-line talk nil nil)))))
(talking-to-myself)
=>
I said: "Hello self."
Self replied: "You sent: 'Hello self.'"
I said: "Why don't you say something original?"
Self replied: "You sent: 'Why don't you say something original?'"
I said: "Talk to you later then. Bye."
Self replied: "You sent: 'Talk to you later then. Bye.'"
This example illustrates a server which picks a free port and records the socket. The last form queries the socket for the port used.
(defvar *my-socket* nil)
(defun my-announce-function (socket condition)
(if socket
(setf *my-socket* socket)
(my-log-error condition)))
(comm:start-up-server :service nil
:error nil
:announce 'my-announce-function)
(multiple-value-bind (address port)
(comm:get-socket-address *my-socket*)
port)