[Openmcl-devel] Playing with sockets

R. Matthew Emerson rme at clozure.com
Tue Feb 12 07:52:10 PST 2013

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.

More information about the Openmcl-devel mailing list