我已经将这个问题撞到了墙上几个小时。我正在编写一个FTP客户端来从远程FTP服务器检索文件(标准的php ftp工具只返回真或假响应 - 我需要错误代码和消息)。它仍在进行中,但我发现我可以正常下载单个文件,但当我尝试下载两个或更多PASV请求时,不会返回打开数据所需的IP地址和端口号连接。我真的很难理解为什么所以任何帮助都会非常感激。提前致谢! ç
这是代码......
include_once "FTP/socketFTP.php";
$host = "127.0.0.1";
$port = 21;
$username = "xxx";
$password = "yyy";
$ftpClient = new socketFTP();
if ($ftpClient) {
$ftpClient->destinationFolder = 'c:\\users\\xxx.yyy\my-data\\';
$status = $ftpClient->connect($host, $port);
$status = $ftpClient->login($username, $password);
$status = $ftpClient->chdir("/test-data/");
//$status = $ftpClient->getFile('foo.txt');
$entries = $ftpClient->dirList();
$status = $ftpClient->retrieveAllFilesInDirectory();
$ftpClient->close();
}
<?php
class socketFTP {
private $control;
private $host;
public $destinationFolder;
public function connect($host, $port = 21, $timeout = 90) {
if (!is_string($host) || !is_integer($port) || !is_integer($timeout)) {
throw new exception("Invalid host, port or timeout properties provided.");
}
//$addr = gethostbyname($host);
$addr = $host;
$control = stream_socket_client("tcp://" . $addr . ":" . $port, $errno, $errorMessage);
do {
$content[] = fgets($control, 8192);
$array = socket_get_status($control);
} while ($array['unread_bytes']);
$status = $this->retrieveResponse($content);
if ($control === false) {
throw new exception("Unable to connect to server: " . $host . " port: " . $port . ". Please check network and server status.");
}
$this->control = $control;
$this->host = $host;
return true;
}
public function login($username, $password) {
fwrite($this->control, "USER " . $username . "\r\n");
$content = array();
do {
$content[] = fgets($this->control, 8192);
$array = socket_get_status($this->control);
} while ($array['unread_bytes'] > 0);
fwrite($this->control, "PASS " . $password . "\r\n");
do {
$content[] = fgets($this->control, 8192);
$array = socket_get_status($this->control);
} while ($array['unread_bytes'] > 0);
// TODO - return status
return true;
}
public function close() {
fclose($this->control);
}
public function chdir($pwd)
{
if (!is_string($pwd)) {
return array('code' => '550', 'message' => 'CWD Failed. ' . $pwd . 'does not exist');
}
fwrite($this->control, "CWD " . $pwd . "\r\n");
do {
$content[] = fgets($this->control, 8192);
$array = socket_get_status($this->control);
} while ($array['unread_bytes'] > 0);
return true;
}
public function getFile($filename) {
$content = array();
fwrite($this->control, 'PASV ' ."\r\n");
do {
$content[] = fgets($this->control, 128);
$array = socket_get_status($this->control);
} while ($array['unread_bytes']);
$status = $this->retrieveResponse($content);
$dataPort = $this->getDataPortNumber($status['message']);
if (is_numeric($dataPort) and $dataPort > 0) {
$client = stream_socket_client("tcp://" . $this->host . ":" . $dataPort, $errno, $errorMessage);
if ($client === false) {
throw new UnexpectedValueException("Failed to connect: $errorMessage");
}
$content = array();
fwrite($this->control, 'RETR ' . $filename ."\r\n");
do {
$content[] = fgets($this->control, 8192);
$array = socket_get_status($this->control);
} while ($array['unread_bytes']);
$this->retrieveResponse($content);
$contents = stream_get_contents($client);
fclose($client);
$status = $this->saveFile($filename, $contents);
} else {
throw new UnexpectedValueException("Failed to connect - Invalid port number specified for a data connection in FTP->getFile()");
}
return $status;
}
public function dirList() {
fputs($this->control, 'PASV' ."\r\n");
do {
$content[] = fgets($this->control, 8192);
$array = socket_get_status($this->control);
} while ($array['unread_bytes']);
$status = $this->retrieveResponse($content);
$dataPort = $this->getDataPortNumber($status['message']);
echo "Port: $dataPort<br />";
$client = stream_socket_client("tcp://" . $this->host . ":" . $dataPort, $errno, $errorMessage);
if ($client === false) {
throw new UnexpectedValueException("Failed to connect: $errorMessage");
}
fputs($this->control, 'LIST' ."\r\n");
do {
$content[] = fgets($this->control, 8192);
$array = socket_get_status($this->control);
} while ($array['unread_bytes']);
$this->retrieveResponse($content);
$contents = stream_get_contents($client);
fclose($client);
$entry = array();
$files = explode("\n", trim($contents));
foreach ($files as $file) {
$fileData = preg_split("/\s+/", $file);
$permissions = $fileData[0];
if (substr($permissions, 0, 1) != 'd') {
$entry[] = $fileData[8];
}
}
return $entry; // A list if filenames
}
public function retrieveAllFilesInDirectory() {
$files = $this->dirList();
foreach ($files as $file) {
echo "Retrieving file: $file<br />";
$this->getFile($file);
}
}
public function getDataPortNumber($message) {
$start = strpos($message,'(');
$data = substr($message, $start);
$data = preg_replace("/[().]/","",$data);
$elements = split(',', $data);
$port = $elements[4] * 256 + $elements[5];
return $port;
}
function retrieveResponse($message) {
$info = $message[0];
$code = substr($info, 0, 3);
$message = substr($info,3);
echo $code . " => " . $message . "<br />";
return array('code' => $code, 'message' => $message);
}
function saveFile($filename, $contents) {
$f = $this->destinationFolder . $filename;
echo "Filename : $f<br />";
$status = file_put_contents($f, $contents);
}
function fwrite_with_retry($sock, &$data)
{
$bytes_to_write = strlen($data);
$bytes_written = 0;
while ( $bytes_written < $bytes_to_write )
{
if ( $bytes_written == 0 ) {
$rv = fwrite($sock, $data);
} else {
$rv = fwrite($sock, substr($data, $bytes_written));
}
if ( $rv === false || $rv == 0 )
return( $bytes_written == 0 ? false : $bytes_written );
$bytes_written += $rv;
}
return $bytes_written;
}
}
我得到的回应是:
220 =&gt;欢迎...... 227 =&gt;进入被动模式(127,0,0,1,229,104) 港口:58728 227 =&gt;进入被动模式(127,0,0,1,229,104) 226 =&gt;转移确定
注意:未定义的偏移量:第180行的C:\ xampp \ htdocs \ socket-ftp \ FTP \ socketFTP.php中的4
注意:未定义的偏移量:在第180行的C:\ xampp \ htdocs \ socket-ftp \ FTP \ socketFTP.php中为5 端口:0
警告:stream_socket_client():无法在C:\ xampp \ htdocs \ socket-ftp \ FTP \ socketFTP中连接到tcp://127.0.0.1:0(请求的地址在其上下文中无效。)。第132行的PHP
致命错误:未捕获的异常&#39; UnexpectedValueException&#39;消息&#39;连接失败:请求的地址在其上下文中无效。 &#39;在C:\ xampp \ htdocs \ socket-ftp \ FTP \ socketFTP.php:134堆栈跟踪:#0 C:\ xampp \ htdocs \ socket-ftp \ FTP \ socketFTP.php(162):socketFTP-&gt; dirList( )#C:\ xampp \ htdocs \ socket-ftp \ socketGo.php(21):socketFTP-&gt; retrieveAllFilesInDirectory()#main {main}抛出C:\ xampp \ htdocs \ socket-ftp \ FTP \ socketFTP。第134行的PHP