4

こんにちは。fsockopenを使用してMinecraftサーバーにpingを実行するために作成されたスクリプトがあります。代わりにcURLを使用するように変換する方法があるかどうか疑問に思いましたか?

関数は次のとおりです。

function pingserver($host, $port=25565, $timeout=30) {
//Set up our socket
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
if (!$fp) return false;

//Send 0xFE: Server list ping
fwrite($fp, "\xFE");

//Read as much data as we can (max packet size: 241 bytes)
$d = fread($fp, 256);

//Check we've got a 0xFF Disconnect
if ($d[0] != "\xFF") return false;

//Remove the packet ident (0xFF) and the short containing the length of the string
$d = substr($d, 3);

//Decode UCS-2 string
$d = mb_convert_encoding($d, 'auto', 'UCS-2');

//Split into array
$d = explode("\xA7", $d);

//Return an associative array of values
return array(
    'motd'        =>        $d[0],
    'players'     => intval($d[1]),
    'max_players' => intval($d[2]));
}

この関数はローカルサーバーで実行している場合にのみ機能するようです。そのため、リモートサーバーで実行できるようにcURLに変換したいと思います。

4

1 に答える 1

4

問題は解決したと思いますが、コマンドラインのMinecraft'ping'も必要だったので、PHPコードをスタンドアロンのPerlスクリプトに移植し、他の誰かが同様のものを必要とする場合に備えて、ここで共有したいと思いました。スクリプトはコアモジュールのみを使用するため、Perlがインストールされている場所であればどこでも機能するはずです。

#!/usr/bin/perl
##############################################################################
#
# Script:   mcping
#
# Author:   Grant McLean <grant@mclean.net.nz>
#
# Description:
#
# 'ping' a minecraft server to check it's alive
#

use strict;
use warnings;

use IO::Socket;
use Pod::Usage;
use Getopt::Long  qw(GetOptions);
use Encode        qw(decode);
use Time::HiRes   qw(gettimeofday tv_interval);

my(%opt);

if(!GetOptions(\%opt, 'help|?')) {
    pod2usage(-exitval => 1,  -verbose => 0);
}

pod2usage(-exitstatus => 0, -verbose => 2) if $opt{help};

my $target = shift or pod2usage(
    -exitval => 1,  -verbose => 0, -message => 'No host specified'
);

my $port = 25565;
if($target =~ /(.*?):(\d+)$/) {
    $target = $1;
    $port   = $2;
}

ping_server($target, $port);

exit 0;


sub ping_server {
    my($host, $port) = @_;

    my $t0 = [gettimeofday];
    my $s = IO::Socket->new(
        Domain   => AF_INET,
        PeerAddr => $host,
        PeerPort => $port,
        Proto    => 'tcp',
    ) || die "$!\n";

    $s->autoflush(1);
    print $s "\xFE";

    sysread($s, my $resp, 256);
    my $elapsed = tv_interval($t0);

    die "Malformed response after connect\n" unless $resp =~ /^\xFF/;

    substr($resp, 0, 3, '');

    $resp = decode('UCS-2', $resp);

    my($motd, $players, $max_players) = split /\x{A7}/, $resp;

    print "Msg of the Day:  $motd\n"
        . "Players Online:  $players\n"
        . "Max Players:     $max_players\n";
    printf "Ping Time:       %5.3fs\n", $elapsed;
}


__END__

=head1 NAME

mcping - 'ping' a minecraft server

=head1 SYNOPSIS

  mcping [options] host-or-ip:port

  Options:

   -?     more detailed help message

=head1 DESCRIPTION

Attempts to connect to a minecraft server on the specified host:port.  On
success, a brief report like this will be printed:

  Msg of the Day:  A Minecraft Server
  Players Online:  2
  Max Players:     10
  Ping Time:       0.175s

If the :port is not specified, the default port number of 25565 will be used.

=head1 OPTIONS

=over 4

=item B<-?>

Display this documentation.

=back

=head1 AUTHOR & COPYRIGHT

This script was written by Grant McLean ( grant@mclean.net.nz ) as a Perl port
of a similar PHP script here: http://stackoverflow.com/questions/10055839/

This script may be freely used, copied and distributed under the same terms as
Perl itself.

=cut
于 2012-06-07T06:13:58.153 に答える