使用 cURL 在 PHP 中 ping Minecraft 服务器

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,这样我就可以在远程服务器上运行它。


这在远程服务器上运行良好,我刚刚测试过了。 - Jack
嗯...我收到了这个错误信息:警告:fsockopen() [function.fsockopen]:无法连接到xx.xx.xx.xx:25565(连接被拒绝),位于/home/user/public_html/mc.php的第6行 - CJT3
听起来你可能有某种防火墙,或者更有可能是连接到了一个错误的主机/端口。 - Jack
事实证明这是我的托管公司的问题,他们已经解决了。 - CJT3
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: https://dev59.com/52LVa4cB1Zd3GeqPwW8v

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

=cut

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接