[Openmcl-devel] [OpenMCL/CCL Devel] Send and receive data via CCL sockets
Gary Byers
gb at clozure.com
Mon Sep 8 17:22:49 PDT 2008
If only CL provided some function to FORCE-OUTPUT on a buffered stream.
That hypothetical FORCE-OUTPUT function sure would come in handy in
cases like this ...
One might legitimately ask why the lisp doesn't call FORCE-OUTPUT
for you, as it does on *TERMINAL-IO* and its synonym streams. I
could imagine that making output line-buffered (e.g., to have
FORCE-OUTPUT called every time a newline is written) could sometimes
be useful, as could forcing output before reading input. Whether
those behaviors would in fact be useful depends lot on the higher
level protocol. You can probably generalize some of this, but
I think that it's hard to do a very good job of that.
(For instance, when writing an SMTP server, it would be desirable to
call FORCE-OUTPUT after sending the last line of a multiline response,
but it might be less efficient to call FORCE-OUTPUT after each line.
You might wind up writing a server that reads command lines and
writes response lines as something like:
(loop
(force-output socket) ; ensure that buffered output is sent
(let* ((command-lines ()))
;; read one or more command lines
(do* ((line (read-line socket nil nil) (read-line socket nil nil)))
((null line)) ; EOF ?
(push line command-lines)
(if (not (is-continuation-line line))
(return)))
(process-command-lines (nreverse command-lines))))
That's -probably goint to perform at least a little better than
something that automatically did FORCE-OUTPUT on every newline,
and sometimes it'd perform a lot better.
(I'd be willing to believe that a :JUST-LINE-BUFFER-IT-I-DONT-CARE
option to MAKE-SOCKET and other stream-creation functions could
be useful, but it's less clear that that's a good default.)
On Mon, 8 Sep 2008, David L. Rager wrote:
> Nice, that works quite well, thanks.
>
> Now, I'm trying to figure out how to actually send and receive data.
> If I use format to write a string to the stream, how do I make the
> other process read the string? A read (triggered with a call to
> "(read der)" of the stream on the server just hangs (a backtrace shows
> it's waiting in FD-READ, which was called by FD-Stream-Advance).
>
> Note: "der" is set to the stream generated from the socket labeled
> "der" in the example sent out by Karsten.
>
> On Mon, Sep 8, 2008 at 4:31 PM, David Rager <ragerdl at gmail.com> wrote:
>> Nice, that works quite well, thanks.
>>
>> Now, I'm trying to figure out how to actually send and receive data.
>> If I use format to write a string to the stream, how do I make the
>> other process read the string? A read (triggered with a call to
>> "(read der)" of the stream on the server just hangs (a backtrace shows
>> it's waiting in FD-READ, which was called by FD-Stream-Advance).
>>
>> Note: "der" is set to the stream generated from the socket labeled
>> "der" in the example sent out by Karsten.
>>
>> On Mon, Sep 8, 2008 at 2:42 PM, Karsten Poeck <karsten.poeck at gmail.com> wrote:
>>> Hello,
>>> I use the following:
>>> (defun %make-client-socket (host &key port)
>>> (ccl:make-socket :remote-host host
>>> :remote-port port
>>> :type :stream
>>> :connect :active
>>> :format :bivalent))
>>>
>>> (defun %make-server-socket (&key port)
>>> (ccl:make-socket :local-port port
>>> :type :stream
>>> :connect :passive
>>> ;;; at least for debugging
>>> :nodelay t
>>> :backlog 5
>>> :reuse-address t
>>> :format :bivalent))
>>>
>>> (defun %wait-for-connection (socket)
>>> (let ((stream (ccl:accept-connection socket :wait t)))
>>> stream))
>>>
>>>
>>> Listener 1
>>> (setq der ( %make-server-socket :port 8000))
>>> -> #<CCL::LISTENER-SOCKET #x3000417DFBCD>
>>>
>>> ( %wait-for-connection der)
>>> -> Blocks
>>>
>>> Listener 2
>>> -> (setq die (%make-client-socket "127.0.0.1" :port 8000))
>>> #<BASIC-TCP-STREAM ISO-8859-1 (SOCKET/17) #x30004181F69D>
>>> and listener 1 unblocks
>>> #<BASIC-TCP-STREAM ISO-8859-1 (SOCKET/18) #x30004183FD6D>
>>>
>>> and now on both sides you have streams
>>> salud2
>>>
>>> Karsten
>>>
>>> In article
>>> <6921cfbe0809081148h2d850c76g6bb6bec4cb7ca144 at mail.gmail.com>,
>>> "David Rager" <ragerdl at cs.utexas.edu> wrote:
>>>
>>>> Hello,
>>>>
>>>> Please excuse my extremely naive question. I've been reading many
>>>> documents over the last week and have yet to find a definitive way to
>>>> send and receive data via sockets in CCL. How does one send/receive
>>>> data over TCP in CCL? I got the OpenMCL REPL from 2004ish working (a
>>>> rather nice piece of work btw). But, now I'd like to do more advanced
>>>> things like send data back instead of a string.
>>>>
>>>> As a starting point, here's some of what I've been doing:
>>>>
>>>> In LISP session 0:
>>>> (setf *socket?* (make-socket :local-host "127.0.0.1" :local-port 24365
>>>> :remote-host "127.0.0.1" remote-port 23459 :connect :passive :type
>>>> :stream :reuse-address t))
>>>>
>>>> In LISP session 1:
>>>> (setf *socket?* (make-socket :local-host "127.0.0.1" :local-port 23459
>>>> :remote-host "127.0.0.1" remote-port 24365 :connect :active :type
>>>> :stream :reuse-address t))
>>>> (format *socket* "hello")
>>>>
>>>> In LISP session 0:
>>>> (read-line *socket* nil nil)
>>>> ; now I hit an error about how *socket* isn't of type stream. How do
>>>> I make *socket* of type stream?
>>>>
>>>> I'm almost positive reuse-address is optional (I think t is the default?).
>>>>
>>>> Thanks!
>>>> David
>>>>
>>>>
>>>> If it matters, I'm on the official CCL64 1.2 release (++official release).
>>>
>>> _______________________________________________
>>> Openmcl-devel mailing list
>>> Openmcl-devel at clozure.com
>>> http://clozure.com/mailman/listinfo/openmcl-devel
>>>
>>
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel
>
>
More information about the Openmcl-devel
mailing list