http://www.perlmonks.org?node_id=11104303


in reply to Re^6: Querying program port
in thread Querying program port

Here is a Perl solution that not only indicates which port answered, but also decodes that backslash-delimited blob into a nicely formatted list.

This script takes full advantage of UDP by sending all of the queries before attempting to read a response.

#!/usr/bin/perl # A simple tool to find a UDP server on a known host, adapted from an # example in perlipc. The server speaks a strange protocol. # This script is free software; you can redistribute it and/or modify +it # under the same terms as Perl itself. use strict; use warnings; use Socket; # Configuration my $HOST_ADDR = '333networks.com'; my @PORTS = (27895 .. 27905); my $TIMEOUT = 3.0; # seconds # Translate network addresses my $Host = inet_aton $HOST_ADDR; my $UDP_Protocol = getprotobyname 'udp'; # Open socket socket(SOCKET, PF_INET, SOCK_DGRAM, $UDP_Protocol) or die "socket: $!" +; # Go! foreach my $port (@PORTS) { defined(send(SOCKET, qq[\\status\\], 0, sockaddr_in($port, $Host))) or die "send: $!" } # Any replies within timeout period? my @Reports = (); # each element: [$sockaddr, $data] my $Start_time = time; my $rout; my $rin = ''; vec($rin, fileno(SOCKET), 1) = 1; while ((time < ($Start_time + 2*$TIMEOUT)) && (select($rout = $rin, undef, undef, $TIMEOUT))) { my $remote_sockaddr; my $report; ($remote_sockaddr = recv(SOCKET, $report, 4096, 0)) or die "recv: $! +"; push @Reports, [$remote_sockaddr, $report]; } # Parse and pretty-print unless (scalar @Reports) { print "No responses received.\n"; exit 1 } foreach my $report (@Reports) { my ($remote_port, $remote_address) = sockaddr_in $report->[0]; my @rows = (); # cannot use hash due to duplicate keys { local $_ = $report->[1]; # \---- $1: key $2: value ----\ while (m/\\([^\\]+)\\([^\\]*)(?=\\|\z)/gs) { push @rows, [$1, $2] +} } my $namewidth = 0; foreach my $row (@rows) { $namewidth = length $row->[0] if length $row->[0] > $namewidth } print "Response from port $remote_port:\n"; printf ' %*s: %s%s', $namewidth, @$_, "\n" for @rows; } exit 0 __END__

Sample output:

Response from port 27900: gamename: 333networks gamever: MS-perl 2.4.3 location: 0 queryid: 72.1 hostname: master.errorist.tk (The Errorist Network Master Server) hostport: 28900 gametype: MasterServer mapname: 333networks numplayers: 14 maxplayers: 2965 gamemode: openplaying queryid: 72.2 mutators: 333networks synchronization, UCC Master applet synchron +ization, Server Status Checker AdminName: Syntax-Error AdminEMail: syntax@errorist.tk queryid: 72.3 final:

Your homework assignment is to learn enough of Perl to explain how this script works. I have used some odd features and deliberately written parts of the script to illustrate some features of Perl that I would not have used if this were not intended as a teaching aid. Learning Perl enough to complete this assignment may take a while, so you are not expected to present it here for grading, only to yourself. And remember, if you cheat on this assignment, you are only cheating yourself.

Replies are listed 'Best First'.
Re^8: Querying program port
by CougarXR7 (Acolyte) on Aug 12, 2019 at 01:25 UTC
    Thank you! I tried sending you a PM but I need to learn how to use this forum. I will be sending you a pm once I learn how.
    Tried running script in terminal and it gave me a Permission denied.

      Did you try running it as perl findgame.pl (or whatever name you assigned to it)? That is usually a local error, related to the file not being marked executable. Also try: chmod a+x findgame.pl (or whatever name you saved it as).

        Before I get into Permission denied, I need to address my mistakes I made .
        333networks is not a game, but a game server browser. That uses UDP port 27900 and TCP port 28900. I sent that info so you could have some idea of what I was trying to do, forgetting 333networks was a browser and not a game. That explains the weirdness you seen with 333networks.
        You launch a game, your game send 333networks a UDP heartbeat packet with your game server info.
        I launch the same game, wanting to find a server to play on, I click scan internet in the game browser, using TCP protocol.
        333networks then sends me your game server info, highlighting it, clicking join, we are now using UDP protocol connecting our games, and no longer using 333networks game server browser.
        Games use TCP protocol to be queried, that why Jetfighter returned nothing using UDP port 8181, but did using TCP port 8182. You said the -u means UDP, that really has me confused because nc 12.234.56.789 8182 -u , \status\, returned a response from Jetfighter, using a TCP port with -u UDP switch resulted in a response, confusing!
        The following is from my Ubuntu terminal,
        $ /home/cougarxr7/Perl/portscript333.pl
        bash: /home/cougarxr7/Perl/portscript333.pl: Permission denied. Now I change permissions on the file to run as program.
        $ /home/cougarxr7/Perl/portscript333.pl
        bash: /home/cougarxr7/Perl/portscript333.pl: /usr/bin/perl^M: bad interpreter: No such file or directory.
        chmod a+x /home/cougarxr7/Perl/portscript333.pl.
        The terminal started a new session after doing the above input. Tried again same results.
        I am asking, since I cannot run this script, Can you please rewrite it with port inc? As I described earlier in my post.
        Then I can watch the terminal displaying port inc. starting with port 25000.
        ~$ 25001
        ~$ 25002
        ~$ 25003
        Keeps incrementing by 1 until game response/replies.
        I like the #parse and pretty print!
        I hope you will rewrite this script for me!
        I now realize when sending a pm, You Said means message sent!
        For kicks and giggles, I wound up #'ing every line of code in that file,starting at the bottom and still got permission denied. So it's not what's in the file but the file itself.
      You have a pm. ... I tried sending you a PM... I will be sending you a pm...

      Just out of curiosity, what's a "PM"?


      Give a man a fish:  <%-{-{-{-<

        For the benefit of anyone reading this later, "PM" was evidently common forum-speak for the feature that PerlMonks calls "/msg". Those messages showed up in my Inbox.