[Openmcl-devel] Playing with sockets
gb at clozure.com
Tue Feb 12 20:15:12 UTC 2013
Mpte that Matt's code calls FINISH-OUTPUT; this is also likely to be significant.
CCL's streams (including those streams that're based on sockets) are
"fully buffered", which means that data written to them is ordinarily
only written to the underlying device (socket or other file
1) when the stream's output buffer is full
2) when the stream is closed
3) when FORCE-OUTPUT or FINISH-OUTPUT is called on the stream
Other implementations may do buffering differently; I think that it's
fairly common in other implementations to make streams be
"line-buffered" (so that something like FORCE-OUTPUT happens whenever
a #\newline is written to the stream.)
If you remove the call to FINISH-OUTPUT from Matt's example, you may find
that the following READ-LINE call will wait forever for the server to respond
to a request that it's never seen.
On Tue, 12 Feb 2013, R. Matthew Emerson wrote:
> On Feb 12, 2013, at 8:18 AM, Stefano Bennati <bennati at cognition.uni-freiburg.de> wrote:
>> Dear Clozure-ers,
>> I am trying to create a simple function that queries a server and returns the answer.
>> I am using the socket functions integrated in Clozure to do so.
>> Until now I succeeded in sending the request to the server with the following code
>>> (ccl:with-open-socket (socket :address-family :internet :type :stream :connect :active
>>> :remote-host MY-HOST :remote-port MY-PORT) (format socket MY-STRING))
>> But now I have no idea how to read the answer (string) that the server gives in response to MY-STRING.
>> The only function that I have found, receive-from, operates only with passive sockets and I cannot find the way to convert my socket into a passive one.
>> There must be a simpler way that I am missing
> Here's an example:
> (defun foo ()
> (with-open-socket (socket :remote-host "www.clozure.com" :remote-port 80
> :external-format '(:character-encoding :ascii
> :line-termination :crlf))
> (write-string "HEAD / HTTP/1.0" socket)
> (terpri socket)
> (format socket "Host: www.clozure.com~2%")
> (finish-output socket)
> (read-line socket)))
> We evaluate this, and get
> "HTTP/1.1 302 Found"
> This shows:
> 1. The socket you get from make-socket (and thus from with-open-socket) is
> a regular lisp stream.
> 2. You need to be sure that you use the correct external format. Binary
> streams are simple: just specify an external format of (unsigned-byte 8)
> and use read-byte/read-sequence and you're all set.
> Sometimes character streams can be tricky to get right. HTTP is probably
> not the greatest example to use here. Since the headers are text, it seems
> attractive to use a character stream, but the body is encoded in all sorts
> of ways that a character stream can't really be used for. Anyway, getting
> into the minutiae of HTTP isn't the point of my example.
> 3. Note that the external format specifies :crlf as the line termination.
> This turns the newline produced by terpri and ~% into a CRLF sequence on
> output, and turns CRLF to newline on input. (HTTP expects header lines
> to be CRLF terminated.)
> I hope that helps you.
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
More information about the Openmcl-devel