eliot@milton.acs.washington.edu (Eliot Lim) (04/12/90)
Can anyone tell me why the following piece of code fails? I've been banging my head on the wall for days and I've had 2 other people look at the code for obvious bugs. I will only list pseudo code as I'd like to know if there's anything fundamentally wrong with my approach. The program is a file server/client using sockets for transfer. The client program prompts the user for a filename, sends it through the socket to the server, the server reads the file and sends it back through the socket. The client program behaves like this: 1) First iteration produces 100% expected results 2) Second iteration produces an empty output file 3) Third iteration the program exits, even though there are no exits in the code. (i.e. the code is a pure infinite loop; the error() routine was set up to print a msg and return. 4) No error messages are ever printed by the client or the server. Assume that the socket is already connected. client: while(1){ prompt(input); send(socket,input); creat(outfile); while(1){ if ((result = recv(socket)) < 0) error; if result == 0 break; if ((result = write(outfile) < 0) error; } close(outfile) } server: while(1){ waitfor(input); open(input); while(1){ if ((result == read(input) < 0)) error; if result == 0 { fflush(socket); break; } if ((result == send(socket) < 0)) error; } close(input); } The client/server code has been ported to different machines and flavors of unix and it produces identical, consistent results every time, so I'm ruling out an OS bug. Specifying identical or different input/output files do not make any difference. I have also tried different buffer sizes with no results. Any help or advice would be appreciated. Eliot
penneyj@servio.UUCP (D. Jason Penney) (04/12/90)
In article <2812@milton.acs.washington.edu> eliot@dodongo.engr.washington.edu (Eliot Lim) writes: >Can anyone tell me why the following piece of code fails? I've been >banging my head on the wall for days and I've had 2 other people look >at the code for obvious bugs. I will only list pseudo code as I'd >like to know if there's anything fundamentally wrong with my approach. > >The program is a file server/client using sockets for transfer. >The client program prompts the user for a filename, sends it through >the socket to the server, the server reads the file and sends it back >through the socket. > [snip] Acch! Phht! I hope this gets added to the regularly asked questions file. BSD stream sockets are STREAMS. This means that they don't honor any kind of record boundaries. (BTW, the fflush(socket) is rather alarming; if you're using read(2) and write(2), this means socket is an fd, whereas fflush is expecting a FILE* for an argument. If you're using fdopen() to associate a FILE* with the socket, other peculiar things can happen.) This means that the program as written will produce unpredictable results unless you add some syntax so that the server can distinguish the file name from input. Further, the number of bytes sent in any single call on the server side doesn't necessarily have any correlation to the number of bytes received on the client side. Why the program exits prematurely can't be answered by examining the pseudo-code. You MUST have some kind of exit routine, such as fault handler, or some other exit condition. It's possible that I've missed the boat entirely, because the pseudo-code doesn't show things like the exact syscalls used to open, read and write the socket. If this is the case, please accept my apologies, and follow up with e-mail; perhaps I can help. In any event, my original point holds: the fact that BSD stream sockets do NOT observe record boundaries is a good candidate for the commonly-asked questions posting. -- D. Jason Penney Ph: (503) 629-8383 Beaverton, OR 97006 uucp: ...uunet!servio!penneyj (penneyj@slc.com) "Talking about music is like dancing about architecture." -- Steve Martin
brnstnd@stealth.acf.nyu.edu (04/15/90)
In article <2812@milton.acs.washington.edu> eliot@dodongo.engr.washington.edu (Eliot Lim) writes: > The program is a file server/client using sockets for transfer. > The client program prompts the user for a filename, sends it through > the socket to the server, the server reads the file and sends it back > through the socket. auth to the rescue... foo: #!/bin/sh # Look Ma, no passwords! (date; echo "$PROTO:$REMOTE") >> fileserver.log # security: only allow requests if authenticated and from right source if [ x"$PROTO:$REMOTE" = xTCP:eliot@128.19.95.8 ] then cat < "`head -1`" # might want to strip out slashes with | tr -d / fi server% attachport -X -p50505 ./foo & dodongo% authtcp -R server 50505 sh -c 'echo -n Filename:" ";head -1>&6;cat<&6' The -X on attachport means that the user on the server side isn't authenticated; the -R on authtcp means not to look for the server's authentication. For more security in case 50505 might not be free, -p50505 should be replaced by -1, the port chosen by the system should be communicated in some other way, and -R/-X should disappear in favor of client REMOTE tests. ---Dan