ftp_connect() 函数建立一个到指定FTP服务器的连接。
ftp_connect(string $hostname, int $port = 21, int $timeout = 90): resource|false
| 参数 | 描述 |
|---|---|
$hostname |
必需。要连接的FTP服务器主机名或IP地址。
可以是:
|
$port |
可选。FTP服务器端口号,默认是21。
注意:某些FTP服务器可能使用其他端口,如990(FTPS)或22(SFTP,但需使用SSH2扩展)。 |
$timeout |
可选。连接超时时间(秒),默认是90秒。 |
false建立到FTP服务器的基本连接:
<?php
// FTP服务器信息
$ftp_server = "ftp.example.com";
$ftp_port = 21;
$timeout = 30;
// 建立FTP连接
$conn_id = ftp_connect($ftp_server, $ftp_port, $timeout);
if ($conn_id) {
echo "成功连接到FTP服务器: {$ftp_server}:{$ftp_port}\n";
// 后续操作...
// 例如:ftp_login(), ftp_pasv(), ftp_nlist()等
// 最后关闭连接
ftp_close($conn_id);
} else {
echo "无法连接到FTP服务器: {$ftp_server}:{$ftp_port}\n";
echo "错误信息:请检查服务器地址、端口和网络连接\n";
}
?>
<?php
function connectToFTP($server, $username, $password, $port = 21, $timeout = 30) {
// 建立连接
$conn = ftp_connect($server, $port, $timeout);
if (!$conn) {
throw new Exception("无法连接到FTP服务器: {$server}:{$port}");
}
// 尝试登录
if (!ftp_login($conn, $username, $password)) {
ftp_close($conn);
throw new Exception("FTP登录失败: 用户名或密码错误");
}
// 开启被动模式(推荐,特别是通过防火墙时)
if (!ftp_pasv($conn, true)) {
// 被动模式失败不是致命错误,但记录一下
error_log("警告: 无法开启FTP被动模式");
}
return $conn;
}
// 使用示例
try {
$ftp_conn = connectToFTP(
"ftp.example.com",
"myusername",
"mypassword",
21,
30
);
echo "FTP连接和登录成功\n";
// 获取当前目录
$current_dir = ftp_pwd($ftp_conn);
echo "当前目录: {$current_dir}\n";
// 列出文件
$files = ftp_nlist($ftp_conn, ".");
if ($files !== false) {
echo "文件列表:\n";
foreach ($files as $file) {
echo "- {$file}\n";
}
}
// 关闭连接
ftp_close($ftp_conn);
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . "\n";
exit(1);
}
?>
<?php
// 连接到非标准端口的FTP服务器
$servers = [
["host" => "ftp.example.com", "port" => 21, "desc" => "标准FTP"],
["host" => "ftps.example.com", "port" => 990, "desc" => "FTPS(隐式SSL)"],
["host" => "sftp.example.com", "port" => 22, "desc" => "SFTP(注意:需用SSH2扩展)"],
];
foreach ($servers as $server) {
echo "尝试连接: {$server['desc']} ({$server['host']}:{$server['port']})...\n";
$conn = @ftp_connect($server['host'], $server['port'], 10);
if ($conn) {
echo "✓ 连接成功\n";
ftp_close($conn);
} else {
echo "✗ 连接失败\n";
// 检查常见错误
if ($server['port'] == 22) {
echo " 提示:端口22通常用于SFTP,需要使用ssh2扩展而不是ftp扩展\n";
echo " 考虑使用:ssh2_connect() 函数\n";
}
}
echo str_repeat("-", 50) . "\n";
}
?>
<?php
/**
* FTP连接池管理器
*/
class FTPConnectionPool {
private $connections = [];
private $max_connections = 5;
private $timeout = 30;
public function __construct($max_connections = 5, $timeout = 30) {
$this->max_connections = $max_connections;
$this->timeout = $timeout;
}
/**
* 获取FTP连接
*/
public function getConnection($host, $username, $password, $port = 21) {
$key = $this->getConnectionKey($host, $username, $port);
// 检查是否有空闲连接
if (isset($this->connections[$key]) && count($this->connections[$key]) > 0) {
$conn = array_pop($this->connections[$key]);
// 验证连接是否仍然有效
if ($this->isConnectionAlive($conn)) {
echo "从连接池获取现有连接\n";
return $conn;
}
}
// 创建新连接
echo "创建新的FTP连接\n";
$conn = ftp_connect($host, $port, $this->timeout);
if (!$conn) {
throw new Exception("无法连接到FTP服务器: {$host}:{$port}");
}
if (!ftp_login($conn, $username, $password)) {
ftp_close($conn);
throw new Exception("FTP登录失败");
}
ftp_pasv($conn, true);
return $conn;
}
/**
* 归还连接到池中
*/
public function returnConnection($host, $username, $port, $conn) {
$key = $this->getConnectionKey($host, $username, $port);
if (!isset($this->connections[$key])) {
$this->connections[$key] = [];
}
// 如果连接池已满,直接关闭连接
if (count($this->connections[$key]) >= $this->max_connections) {
ftp_close($conn);
echo "连接池已满,关闭连接\n";
} else {
// 保持连接在池中
$this->connections[$key][] = $conn;
echo "连接已归还到连接池\n";
}
}
/**
* 关闭所有连接
*/
public function closeAll() {
foreach ($this->connections as $key => $pool) {
foreach ($pool as $conn) {
if (is_resource($conn)) {
ftp_close($conn);
}
}
$this->connections[$key] = [];
}
echo "所有FTP连接已关闭\n";
}
/**
* 检查连接是否有效
*/
private function isConnectionAlive($conn) {
if (!is_resource($conn)) {
return false;
}
// 尝试执行一个简单的命令来测试连接
try {
$result = @ftp_pwd($conn);
return $result !== false;
} catch (Exception $e) {
return false;
}
}
/**
* 生成连接键
*/
private function getConnectionKey($host, $username, $port) {
return md5("{$host}:{$port}:{$username}");
}
public function __destruct() {
$this->closeAll();
}
}
// 使用示例
$pool = new FTPConnectionPool(3, 30);
try {
// 获取连接
$conn1 = $pool->getConnection("ftp1.example.com", "user1", "pass1");
// 执行一些操作
ftp_chdir($conn1, "/public_html");
$files = ftp_nlist($conn1, ".");
// 归还连接
$pool->returnConnection("ftp1.example.com", "user1", 21, $conn1);
// 再次获取连接(可能从池中获取)
$conn2 = $pool->getConnection("ftp1.example.com", "user1", "pass1");
// 更多操作...
// 归还连接
$pool->returnConnection("ftp1.example.com", "user1", 21, $conn2);
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . "\n";
}
// 脚本结束时会自动关闭所有连接
?>
<?php
// 测试不同超时设置对连接的影响
function testConnectionWithTimeout($host, $port, $timeout) {
$start_time = microtime(true);
// 抑制警告信息
$conn = @ftp_connect($host, $port, $timeout);
$end_time = microtime(true);
$duration = round(($end_time - $start_time) * 1000, 2); // 毫秒
if ($conn) {
echo "✓ 连接成功 ({$duration}ms)\n";
ftp_close($conn);
return true;
} else {
echo "✗ 连接失败 (耗时: {$duration}ms)\n";
return false;
}
}
echo "测试不同超时设置的连接效果:\n";
echo str_repeat("=", 50) . "\n";
$test_host = "ftp.example.com";
$test_port = 21;
// 测试不同的超时时间
$timeouts = [1, 3, 5, 10, 30, 60, 90];
foreach ($timeouts as $timeout) {
echo "超时设置: {$timeout}秒 - ";
testConnectionWithTimeout($test_host, $test_port, $timeout);
}
// 测试连接不存在的主机
echo "\n测试连接不存在的主机:\n";
echo str_repeat("=", 50) . "\n";
$nonexistent_host = "nonexistent-ftp-server.example.com";
echo "尝试连接: {$nonexistent_host}:21 (超时: 5秒) - ";
testConnectionWithTimeout($nonexistent_host, 21, 5);
?>
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| 连接超时 | 服务器无响应、网络问题、防火墙阻止 | 检查网络连接,增加超时时间,检查防火墙设置 |
| 连接被拒绝 | 服务器未运行、端口错误、IP被阻止 | 验证服务器状态,检查端口号,联系服务器管理员 |
| 无法解析主机名 | DNS解析失败、主机名拼写错误 | 检查主机名拼写,尝试使用IP地址,检查DNS设置 |
| SSL连接失败 | 尝试使用ftp_connect()连接SSL端口 | 使用ftp_ssl_connect()进行SSL连接 |
| 连接成功但登录失败 | 用户名/密码错误、权限不足 | 验证凭据,检查用户权限 |
ftp_connect()的返回值,处理连接失败的情况ftp_ssl_connect()进行安全连接,保护数据传输ftp_close()释放资源ftp_connect() |
ftp_ssl_connect() |
|---|---|
| 建立普通的FTP连接 | 建立SSL加密的FTP连接(FTPS) |
| 使用端口21(默认) | 通常使用端口990或21 |
| 数据传输不加密 | 数据传输加密,更安全 |
| 适合内部网络或不敏感数据 | 适合公共网络或敏感数据 |
// 普通FTP连接
$conn = ftp_connect("ftp.example.com", 21);
// SSL FTP连接
$ssl_conn = ftp_ssl_connect("ftps.example.com", 990);
<?php
// 方法1:使用extension_loaded()
if (extension_loaded('ftp')) {
echo "FTP扩展已启用\n";
} else {
echo "FTP扩展未启用\n";
echo "需要在php.ini中启用: extension=ftp\n";
}
// 方法2:使用function_exists()
if (function_exists('ftp_connect')) {
echo "ftp_connect() 函数可用\n";
}
// 方法3:查看phpinfo()
// phpinfo(); // 查看是否有ftp模块信息
// 方法4:命令行检查
// php -m | grep ftp
?>
ftp_login()成功ftp_pasv($conn, true)ftp_pwd()等简单命令| 函数 | 描述 |
|---|---|
ftp_ssl_connect() |
建立SSL加密的FTP连接 |
ftp_login() |
登录FTP服务器 |
ftp_close() |
关闭FTP连接 |
ftp_pasv() |
开启或关闭被动模式 |
ssh2_connect() |
建立SSH连接(用于SFTP) |