Hello,
I am having limited success in using TCPIP to communicate between two
processes and I suspect that it is my incomplete understanding of READ that
is hanging me up. I am using CMUCL 18c on a Linux box and I have read
(although I don't grok) internet.lisp and fd-stream.lisp.
The idea is to have one process accept a connection and then read a form
from the stream, do something with that form, and send a form back to the
other process via the same stream. Using FORMAT and READ I figured I could
send any form that had a read-macro associated with it. It might not be
efficient, but it should work. The communications happens in this sequence:
p1 format-a-form-to-the-stream
p2 read-a-form-from-the-stream
p2 format-a-form-to-the-stream
p1 read-a-form-from-the-stream
I can create the listener socket, accept a connection, create a stream on
the connection, and read a form from the stream but I can't seem to send a
form back to the other process using the same stream. Whenever I get to
the last step, sending a form back to the first process, _both_ processes
get a "Timeout reading #<Stream for descriptor x>" error. Since I thought
that only one process would be trying to read the stream at that point in
time this message is rather confusing. If I comment out the line in p1
that tries to read the result then everything completes as I expect it too.
Here is the server, LOG simply prints the packet to *standard-output* so
that I can see that something is happening and PROCESS-CMD can return
either T, nil, or a list. A packet is of the form ('command '(message)).
(defun server ()
(log 'start)
(let ((listener))
(setf listener (ext:create-inet-listener **port*))
(when (minusp listener)
(error "Can't create listener socket."))
(do (packet socket str)
((eq (car packet) 'shut-down))
(setf socket (ext:accept-tcp-connection listener))
(when (minusp socket)
(error "Error accepting tcp connection."))
(setf str (sys:make-fd-stream
socket
:input t
:output t
:timeout 5))
(setf packet (read str nil 'eof))
(format str "~A " (process-cmd (car packet) (cadr packet)))
(close str))
(ext:close-socket listener)))
And here is the client:
(defun client (packet)
(let ((socket (ext:connect-to-inet-socket *host* *port*))
(ret)
(str))
(when (minusp socket)
(error "Can't connect to server."))
(setf str (sys:make-fd-stream
socket
:input t
:output t
:timeout 5))
(format str "~A " packet)
; Commenting out the next line allows the communicatons
; process to complete.
(setf ret (read str nil 'eof))
(close str)
ret))
I would appreciate any comments on what I _am_ doing as well as on what I
_should_ be doing.
Thanks,
--dennis
········@bellsouth.net writes:
[ snip ]
This one's easy, I think. The reason I think so is that I did
something similar a couple of weeks back, and your code looks similar
to what I did :-)
> And here is the client:
>
> (defun client (packet)
> (let ((socket (ext:connect-to-inet-socket *host* *port*))
> (ret)
> (str))
> (when (minusp socket)
> (error "Can't connect to server."))
> (setf str (sys:make-fd-stream
> socket
> :input t
> :output t
> :timeout 5))
> (format str "~A " packet)
add (finish-output str) here.
> ; Commenting out the next line allows the communicatons
> ; process to complete.
> (setf ret (read str nil 'eof))
> (close str)
> ret))
>
>
> I would appreciate any comments on what I _am_ doing as well as on what I
> _should_ be doing.
The output stream towards the server is buffered, which means
that it won't actually send anything across until a certain number of
output characters have been accumulated. Calling finish-output forces
the characters to be sent immediately.
//Raymond.
--
Raymond Wiker
·············@fast.no