Re: SBCL, udp sockets and sendto

From: Icarus Sparry (usenet_at_icarus.freeuk.com)
Date: 12/05/04


Date: Sun, 05 Dec 2004 17:50:24 GMT

On Sun, 05 Dec 2004 11:42:41 +0000, Christophe Rhodes wrote:

> Icarus Sparry <usenet@icarus.freeuk.com> writes:
>
>> As it is, it only allows me to send strings (because I have specified
>> the BUF argument to be a C-STRING), but they are lisp strings, so do not
>> terminate at embedded NULL characters. It would be nice to be able to
>> send a vector of unsigned bytes directly.
>
> Without having read the rest of your post terribly carefully, as I know
> nothing about sockets: this bit is wrong. Lisp strings, when passed as
> c-strings to foreign functions, do end up with a null-terminated
> representation. If you can come up with a counterexample test case, the
> sbcl developers' mailing list wants to know about it.
>
> Christophe

I stand by my statement. It may be that a NULL has been added, but the
important thing is that the string does not terminate at an embedded NULL.
The sendto function takes a buffer and a length, in the same way that the
'write' call does.

The C interface to 'sendto' takes the following parameters

1) socket descriptor. A small integer, returned from a 'socket' call
2) buffer. A pointer to some memory address
3) length. The number of bytes to send
4) flags. A logior of some values, which my code always sets to 0
5) sockaddr. A pointer to one of a number of weird structures
6) sockaddrlen. The size of the weird structure.

It returns an integer, and does not modify any of the values passed in (C
is not call by reference), nor does it alter any memory that is pointed to
by the two pointers, nor does it keep a copy of the pointers. The 'weird
structures' holds things like the IP address and port number of where to
send the data to. The structures vary in size, e.g. if they have to hold
an IPv4 address or an IPv6 one, and carry tagging information at the start.

The sendto call provides essential functionality needed to make a UDP
server. You create a socket, get a message (using recvfrom), process it,
then send a reply using 'sendto'. The return values of 'recvfrom' gives
you the remote address.

This contrasts with a TCP server. Here you create a socket and 'listen' on
it. When something connects you call 'accept' which creates a new socket,
and future communication to the thing that just connected is via the new
socket.

The existing code in sb-bsd-sockets enables you to write a TCP client, a
UDP client or a TCP server. You can also write a UDP server that services
only one client at a time (by using the 'connect' system call).