This is the mail archive of the
guile@cygnus.com
mailing list for the Guile project.
Re: socket strangeness
- To: knotwell@f5.com
- Subject: Re: socket strangeness
- From: Gary Houston <ghouston@easynet.co.uk>
- Date: 28 Jul 1999 20:05:26 -0000
- CC: guile@sourceware.cygnus.com
- References: <14238.6914.987154.75650@knotwell.f5.com>
| I've a little nasty that's driving me crazy. Under Guile 1.3 (2.1
| glibc), the following small socket server drives me crazy (BTW: I
| understand I've a huge security hole here. . .don't care 'bout that
| yet).
|
| My problem is that the server accepts connections, but it can't
| consistently (successful only the first 2-3 tries) write eval'd data
| (or even just the data itself) to the port. Now, if I make a large
| datastream, ie (range 1 10000 1+ >), I may see _part_ of the socket
| data before the socket is closed.
|
| I have several questions:
|
| 1) should close-port flush mysock automagically? if not, should i
| just flush-all-ports explicitly?
close-port should do whatever flushing is needed. However it
won't make any difference, since sockets are unbuffered by
default. force-output would be more direct than flush-all-ports.
| 2) does display/write have a size "limit"? IOW, should a reader
| expect a large datastream to be sent in chunks?
I think for TCP stream sockets the operating system will take care of
splitting large output into packets and the limit will be quite large.
|
| a more general question:
|
| are there generally known strangenesses to be aware of when using
| sockets under guile?
I got strange behaviour with this example too (linux/glibc-2.1).
I rewrote it in C and still got strange behaviour (see below.)
|
| TIA.
|
| --Brad
|
| ;;; sample server. . .shamelessly stolen from the FAQ
| ;;; BTW: the FAQ example doesn't work on my machine :-(. . .the call
| ;;; to read-line causes the interpreter to exit
True, that's a bug in read-line in Guile 1.3.
|
| (define portnum (string->number (cadr (command-line))))
|
| (let ((port (socket AF_INET SOCK_STREAM 0)))
| (bind port AF_INET INADDR_ANY portnum)
| (listen port 10) ; Queue up to 10 requests.
| (let loop ()
| (let ((p (accept port)))
| (let ((mysock (car p)))
| (let ((mydata (read mysock)))
| (display (eval mydata) mysock))
| (close-port mysock)))
| (loop)))
This version also takes a port on the command line. If I connect
to the server with telnet and type 3 chars <enter> it works, but
more chars than that and it fails. It seems like "close" isn't
giving the output a chance to be written if there are still chars
in the input queue. weird.
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
void error (const char *msg)
{
write (2, msg, strlen (msg));
write (2, "\n", 1);
exit (1);
}
int main (int argc, char *argv[])
{
int server_sock = socket (AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server_addr;
char *tail;
int port;
if (server_sock == -1)
error ("sock");
if (argc != 2)
error ("usage");
port = strtol (argv[1], &tail, 10);
if (*tail != 0)
error ("usage");
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
server_addr.sin_port = htons (port);
if (bind (server_sock, &server_addr, sizeof server_addr) == -1)
error ("bind");
if (listen (server_sock, 10) == -1)
error ("listen");
while (1)
{
char buf[5];
struct sockaddr_in addr;
socklen_t length;
int sock = accept (server_sock, &addr, &length);
int chars;
int i;
if (sock == -1)
error ("accept");
chars = read (sock, buf, sizeof buf);
write (sock, buf, chars);
close (sock);
}
}