4

大家好,我有一个为使用 fsockopen ping Minecraft 服务器而创建的脚本。我想知道是否有办法将其转换为使用 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 回答