[comp.unix.wizards] Socket problem, please help

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