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

I've been slamming my head against the same brick wall all afternoon, so I thought I'd ask for help.

I am attempting to write a TCP server in Perl. This server will listen on a port and accept incoming communications. The first line of the incoming request is read, some decisions are made, and then the rest of the request is read in. I need to get the entire rest of the request into one scalar character string, so I was doing this:
$clientRequest = "";

while (<CLIENT>) {
$clientRequest .= $_;
}

Obviously there is also an ending condition (it checks $_ against a preset "end of file" value).

This, when run, produced some extremely mangled strings. When I tried to print out $clientRequest doing something like this:

print "clientRequest is $clientRequest\n";

I would end up with something like
clientTextest is lastlinesentbyclient

What am I missing? Please tell me it's something obvious and make me feel stupid - at this point, that's the best thing I could hope for. Thanks, Jen

Replies are listed 'Best First'.
RE: Help with string concat and sockets
by merlyn (Sage) on May 17, 2000 at 02:34 UTC
    I usually get scared when I see people inventing a new TCP protocol. There are far too many things to worry about to do this right. If you need a simple RPC structure, just use HTTP as your protocol. Create your server with HTTP::Daemon, and your client then uses LWP::Simple or other parts of the LWP to handle the requests. The neat thing about this is a huge amount of code already provided, and when you need to slide to higher performance or proxying, you can use standard tools.

    Do not invent a protocol. Just say no.

    -- Randal L. Schwartz, Perl hacker

      Hmmm. "Don't reinvent the wheel!"
      Seems apropos, in the interests of saving time and anguish. But what if a person really wants to figure out how to make a wheel (or even a full-fledged oxcart) using nothing but a tree, a rock, a cow, and a knife?
      Maybe one can't truly "know" The Way of The Oxcart until one has built an oxcart from scratch.

      On the other hand, I can see where pestering a race car mechanic with questions about oxcart construction might draw ire.

      e-mail neshura

      Once upon a time, I had to write a suite of test programs for NNTP, HTTP, POP3, SMTP and FTP servers. I used perl because it was preferable to shell scripting, which was the way used prior to that (it only did simple SMTP and NNTP posting operations).

      The problem? The only system that could run these tests was a very unflexibly administered Solaris box with a very stripped install of Perl. Adding modules was strictly verboten, even in my home directory.

      I didn't even have IO::Socket to draw on. I reinvented four wheels, one axle, the concept of glass and I think power steering, but it got the job done and produced some very nice results. You never know when you're going to have to produce results without even 'standard' modules.

      And no, I never figured out why some modules were missing. They had been present once, the docs were still there, but even an extended probe with the find command didn't turn them up.

      5-21-2000 : Fixed the typo in 'steering'

Re: Help with string concat and sockets
by btrott (Parson) on May 17, 2000 at 01:57 UTC
    Jen--one quick idea I had is that perhaps your data has control-M characters in it, which screw up the presentation when you try to look at it in the print statement. I've seen such characters make lines look pretty strange, in the past.

    To test this, you could try join-ing on a carriage return ("\n"), just to see if this is indeed the problem. If your data looks right, this could be it. In which case you'll want to strip control-M characters:

    tr/\cM//d;
Re: Help with string concat and sockets
by jen (Novice) on May 17, 2000 at 01:48 UTC
    Here is some more of the code, in case that's helpful.

    # read the first line of the client's reply to determine which
    # action to take
    $action = <$client>;
    chomp $action;
    print "action is $action\n";

    # set up the variable to match the end tag of the document
    $endAction = $action;
    $endAction =~ s/</<\//g;

    # read the remainder of the client's reply

    $testXML = "";
    while (<$client>) {

    chomp;
    if ($_ eq $endAction) {
    print "end found\n";
    last;
    } #endif

    print "line: $_\n";
    push @clientXML, $_;
    $testXML = join '', $testXML, $_;

    } # end while

    print "testXML is $testXML\n\n";

    And here is what the client is sending:
    <FOO>
    bla
    bla
    bla
    blabababa
    end
    </FOO>
    And here's the result of that print statement in the server:
    endbababas bla

    As you can see, the "testXML is" doesn't even show up except for that one "s"....
Re: Help with string concat and sockets
by turnstep (Parson) on May 17, 2000 at 02:02 UTC
    Hard to say...could be some escape characters sneaking in. Try making the test lines more unique, i.e.
    bla1 abc def ghi end
    and stick a newline and a delimeter by replacing
    $testXML = join '', $testXML, $_; WITH $testXML .= "**$_**\n";
    and see if that helps to debug it at all...
Re: Help with string concat and sockets
by chromatic (Archbishop) on May 17, 2000 at 02:49 UTC
    Instead of using while on a filehandle, you might take advantage of the $/ operator in a block like this:
    { local $/; # undef input record separator $clientRequest = <$client>; # slurp it all in }
    That'll get you the whole rest of the request in one go, instead of having to append a line at a time.

    Jon Udell has a good example of building an HTTP server in Perl with the IO::Socket module, in his dhttp program. (But when I did the same thing, I used HTTP::Daemon.)

Re: Help with string concat and sockets
by jen (Novice) on May 18, 2000 at 22:31 UTC
    Thanks for all the help. Randal, unfortunately, my employer requires a new protocol, and that's what they're getting :)

    The removal of \cM and concatenating with a \n instead of a blank string fixed the problem. Of course, now I'm on to bigger and worse problems, like segfaults - that's how it works though, right?

    Jen