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

I'm writing a script that uses Net:PcapUtils to capture traffic on an ethernet segment. I have the capture working fine, using the Net:PcapUtils::Loop function. Inside that loop, I want the script to stop periodically and listen for a UDP request from a client. The client sends a request like this: 198.59.115.4:34, and the script sends a response like this: 34 198.59.115.4:34, which is a count of how many times it has seen that IP:Port as a destination.

It works, sort of. It counts, it listens, it answers. The problem is this, if it does not receive a request, it seems to wait until it does, not counting in the meantime. I was hoping that an if statement would make it so that if there was no request, it would just continue, but it does not seem to work that way:

$count ++; if ($count == 500) { $MAXLEN = 1024; $PORTNO = 5151; $sock = IO:SOCKET::INET->new(LocalPort => $PORTNO, Proto => 'udp') or die "socket: $@"; if ($sock->recv($request, $MAXLEN)) { ... close($sock); } $count = 0; }
So I start up this script and send a request to it from the client. I get a response. If I don't send a request for an hour and then send one, the count is the same. If I just sit there and send mutliple requests, the count goes up.

Any idea how I can get this to work the way I want?

jgentry@swcp.com

Replies are listed 'Best First'.
Re: Check for request from UDP client
by tadman (Prior) on Jul 05, 2001 at 07:55 UTC
    Two words: "Non-blocking sockets". The problem is that your program stalls on the recv command, waiting for data. If there is no data, it will wait until the end of time for data to arrive.

    So, tell your Socket to be non-blocking using:
    $sock->blocking(0);
    Then it will return right away, even if it didn't read anything.

      Really, it's that easy to stop blocking? Everything I've read about non-blocking talks about using select.

      So I would put this line right after getting the new object?

      $sock = IO::Socket::INET->new(etc.); $sock->blocking(0);

      Thanks for the help.

      jgentry@swcp.com

        Yes, you can use select() as well, which is a more traditional way, since with one call you can check on a large number of sockets simultaneously. If you want to use this, which isn't a bad idea, you might as well use IO::Select instead of the regular one, seeing as how you are using IO::Socket. See the documentation page by clicking on that link, as it contains a useful example.