From: ········@bellsouth.net
Subject: Need help READing a socket stream
Date: 
Message-ID: <p3oL6.1549$Ie.1259087@news2.mia>
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
From: Raymond Wiker
Subject: Re: Need help READing a socket stream
Date: 
Message-ID: <86r8xsqdev.fsf@raw.grenland.fast.no>
········@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