jen has asked for the wisdom of the Perl Monks concerning the following question:

Help (again).

I'm doing something horrible and bad and coding a program that uses a new TCP communications protocol. It reads a string from a client, and then does something with it. This is a stupid question, but how do I know when to stop reading over the socket? while (<$client>) doesn't work. We are trying to send the byte length of the string, but there appears to be some disparity - the client thinks the string length is, say, 747, and the server thinks it's only read 742 bytes, so it hangs.

I know there has to be an obvious solution - can someone please help?

Thanks!

Replies are listed 'Best First'.
Re: When do I stop reading?
by Shendal (Hermit) on Jun 29, 2000 at 19:27 UTC
    I have done a few socket programs using perl as a client. I have never had a problem, in that the server has sent me some sort of eof so that I know when to stop reading. If that doesn't work, check your output -- does the server send you something like "done" that you can key off of?

    Another thought is to use alarm() to limit the amount of time that you're connected.

    Hope that helps.
Re: When do I stop reading?
by jlistf (Monk) on Jun 29, 2000 at 19:24 UTC
    if you're creating both the client and the server application, you could send some sort of end character/string to tell someone that the string has ended.

    otherwise, each command you send a TCP server will get some set response. depending on the command and whether the server responds with an error or not, you will recieve a standard type of reply. its just a matter of knowing when the reply has ended.

    as for the byte disparity, that could be a problem with perl implicitly stripping certain characters from input.

    hope this helps. if not, let me know a little more about what you're trying to do... commands and etc.
Re: When do I stop reading?
by c-era (Curate) on Jun 29, 2000 at 21:36 UTC
    I'm crazy and just set the socket to nonblocking. Then you can use time, a character, or both to stop reading from a socket.
    $flags=fcntl(SOCK,F_GETFL,0); fcntl(SOCK,F_SETFL,$flags | O_NONBLOCK);
Re: When do I stop reading?
by ahunter (Monk) on Jun 30, 2000 at 12:16 UTC
    This sounds like a buffering problem - close the socket on the client when you've finished sending data, or use sysread() and syswrite() (and no other IO calls) to access the socket data. I wrote a longer article on this at Socket.pm nonblocking.

    Update: This happens because all of perl's standard file operators - including things like eof() - are buffered, and read ahead when called. This usually isn't a problem, but with a filehandle that may block (eg a socket or a pipe), perl may block while reading ahead, so you don't see the data until it finishes. Sometimes you write some data to a socket and close it straight away - you won't see the problem here, as perl will stop reading when it gets the EOF. However, if you are trying to do something interactively, where the client socket stays open, you may find perl blocks before you get all the data that is available. sysread() and syswrite() bypass all this, so you can read right up to the last byte using them :-) Remember to check the return values for errors and EOF.

Re: When do I stop reading?
by jen (Novice) on Jun 29, 2000 at 19:52 UTC
    Actually, the problem is in the server - I can't figure out when to make it stop reading. I could have the client send some kind of EOF indicator (and actually that is what I was doing - it's an XML doc so I watched for the closing tag) - but what if the request is malformed and the client doesn't send an EOF? I think that alarm() idea will work well, thanks, Shendal.