Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
G'day shadox,

When you say, "it doesn't do anything", does that really mean "it hangs forever?". If so, I suspect that I know what the problem is.

If your socket is in the (default) blocking mode, your process will block waiting for data whenever you try to read from the socket. If there is a line waiting for you, or one is just about to arrive, then this works wonderfully. However, if you try to read when the remote end isn't intending on sending you anything, your process will sit there waiting for data that will never arrive.

You've got a few options here. Probably the best way of solving things is to look at the data you've received and determine if you're expecting any more. So if you know that every response from the client will end with a "GO AHEAD" you can do something like this:

my $buffer = <$sock>; while ($buffer !~ /GO AHEAD\Z/) { $buffer .= <$sock>; }
Of course, the catch here is that if the remote end doesn't terminate its response as you expect, you're left blocking on the socket forever.

Your second option is to use some sort of timeout, possibly in conjunction with the terminator matching code above. If we're expecting another line, we wait for one to arrive, but we don't block indefinitely. select() is a good way to wait for data to arrive, but allowing you to get out cleanly if it takes too long.

The problem with select is that it doesn't play nicely with buffered I/O, which is what <$socket> gives you. Instead, you'll have to use low-level functions like sysread. This isn't much harder. I'd strongly recommend using IO::Select rather than the core select() call, for sanity reasons:

use IO::Socket; use POSIX qw/BUFSIZ/; # Create an IO::Select object, and ask it to look at $sock. my $s = IO::Select->new(); $s->add($sock); # Continue to read on $sock until things are quiet for # at least one second. my $message; while ($s->can_read(1)) { my $buffer; my $bytes_read = sysread($sock,$buffer,BUFSIZ); unless ($bytes_read) { # Socket just closed, clean it up... } $message .= $buffer; }
Select can be used to examine multiple filehandles and determine which one(s) are available for reading. See the IO::Select manpage for details.

The downside of using select like this is that your process will be spending a second at the end of each message waiting for data that isn't there, or it could miss data in caes of high lag where it takes longer than a second for packets to arrive.

I would personally recommend using the first method of determining when more data is due to arrive, but throwing in a long timeout to catch any "improvements" to the protocol that you don't know about.

Your third option is to go to non-blocking sockets, which will increase your code complexity significantly. If your program needs to be dealing with multiple clients at once, or never wants to be blocking waiting for I/O, then non-blocking sockets are useful. If you only expect to be dealing with a single connection, and you don't have other things to do while waiting for that connection, you definitely want to go with blocking I/O.

Hope this solves the problem.

Cheers,
Paul


In reply to Re: Getting Data from server by pjf
in thread Getting Data from server by shadox

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (6)
As of 2024-04-16 18:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found