This is the mail archive of the guile@cygnus.com mailing list for the Guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: socket strangeness


| 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);
  }
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]