Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Sending & Receiving on a socket

by Indomitus (Scribe)
on Sep 13, 2001 at 09:35 UTC ( [id://112108]=perlquestion: print w/replies, xml ) Need Help??

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

Hi, this is my first post so please bear with me. I learn fast though so please correct me if I'm not following procedure.

I'm just starting out with sockets and I'm trying to write a simple client/server to send data back and forth between each other. The client sends the server something off of STDIN and then the server is supposed to print it out, then reverse it and send it back to the client to be printed out over there. I've got the client sending the data and the server prints it out but the client doesn't print out the reversed string until the next time I enter something on it. That is, if I enter 'hello' I get back nothing but then when I enter 'there' I get back 'olleh'. I'm not sure where I'm going wrong. Here's the relevant parts of my client & server if someone can point me in the right direction.

Client:
print "# "; $msg = <STDIN>; while ($msg !~ /^end$/) { print $sock "$msg"; my $in_msg = <$sock>; print "> ",$in_msg; print "# "; $msg = <STDIN>; }
Server:
$session = $sock->accept(); while (<$session>) { $recv_msg = $_; print $recv_msg; $send_msg = scalar reverse $recv_msg; print $session $send_msg; }
Thanks a lot in advance.

Replies are listed 'Best First'.
Re: Sending & Receiving on a socket
by blakem (Monsignor) on Sep 13, 2001 at 09:52 UTC
    Sounds like you might be Suffering from Buffering. Take a look at the networking examples provided there... They seem to be be quite similiar to the problem you describe.

    -Blake

Re: Sending & Receiving on a socket
by Ryszard (Priest) on Sep 13, 2001 at 09:51 UTC
    try autoflush:
    select (SERVER); $| = 1; select (STDOUT);
Re: Sending & Receiving on a socket
by Beatnik (Parson) on Sep 13, 2001 at 15:14 UTC
    IO::Socket has autoflush... try
    $client->autoflush(1); #client being returned by accept
    in your server code.

    Greetz
    Beatnik
    ... Quidquid perl dictum sit, altum viditur.
(tye)Re: Sending & Receiving on a socket
by tye (Sage) on Sep 13, 2001 at 19:42 UTC

    I'm frustrated by how often I see people using <SOCK> to read from sockets. <SOCK> will hang until it finds either end-of-file or $/. You should use read, sysread, or recv to read from sockets (unless you have a somewhat unusual protocol that always sends end-of-line on the end of each packet, you know that $/ will match what the remote system is sending as end-of-line, and you don't care if your program hangs when something goes wrong with this).

    Your $send_msg = scalar reverse $recv_msg; will move the "\n" to the front of the string which will make trying to read that data with <$sock> not ideal.

    FYI, AFAICT sockets are always unbuffered.

            - tye (but my friends call me "Tye")
      I'm sure I will be downvoted for disagreeing but...

      Using a newline (or CR LF pair) is not that unusual, and is actually rather common. SMTP and POP are two that come to mind and use nothing but CR LF for line endings. Also HTTP, FTP, and IMAP all use CR LF endings extensively (although they do have sections of data reading that is better left to sysread()).

      Doing a <SOCK> at the wrong time is a symptom of not knowing what you are dealing with while using sockets. It is more a problem of not being defensive than it is doing things wrong. Under most protocols (SOCK_DGRAM and recv() excluded) the programmer should make extensive use of alarm() to make sure he is timing out at apropriate waits. Even when doing a read() or sysread() the server or client could block if they have not read enough data to fulfill the protocol.

      Using a newline (or CR LF) is perfectly acceptible, if you know the protocol uses it, or have made up your own that uses it.

      However, when people don't know what they are doing, or aren't defensive, or don't know the protocol, tye is perfectly correct and doing a getline() should be avoided.

      my @a=qw(random brilliant braindead); print $a[rand(@a)];

        I said that it was fairly unusual to have a protocol that always sends end-of-line on the end of each packet. You managed to list only two. However, you have a very good point that text-only (or at least mostly text) protocols have become common (I'm more used to network protocols that don't assume all computers use ASCII -- but I'm just old). (:

        I wanted to state the case against <SOCK> a bit strongly because I've been seeing a lot of code using it when it shouldn't.

        Also note that using alarm() makes your code less portable. Having an alarm() actually trigger can leave Perl "confused". So that isn't a technique that I can highly recommend. Unfortunately, the alternatives are usually even more complicated and have their own faults so building very robust network servers in Perl gets messier than is often expected when programming Perl. ):

        Note that in the node that I was replying to, the author wrote both sides of the "protocol" and perhaps even meant to send "\n" on the end of each packet. Using read would have probably been enough for the person to figure out the mistake and would have been much simpler than trying to write a robust server and client that tries to handle lots of more unusual failure modes gracefully.

        Having something "hang" is one of the more difficult cases to debug and so I stand by my assertion that, in Perl, it is best to not use <> to read from sockets even when you expect that there will be a "\n" on the end of the next packet.

                - tye (but my friends call me "Tye")
Re: Sending & Receiving on a socket
by jepri (Parson) on Sep 13, 2001 at 20:25 UTC
    Your code locks up at this line $msg = <STDIN>; because <STDIN> waits until you type a return before continuing. Perl has no good way to just read one character from the keyboard. There are any number of ways around this problem, and they all suck to a greater or lesser degree.

    Update: Oh yeah, and tyes answer too.

    I almost always program non-blocking so I'd expect the program to hit the keyboard read before getting an answer from the server.

    ____________________
    Jeremy
    I didn't believe in evil until I dated it.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://112108]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (7)
As of 2024-09-09 07:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.