PhP ftp_put 功能限制?

标签 php

我正在研究必须将 33,000 或更多 csv 文件上传到服务器的解决方案。

我的脚本可以正常处理多达 25,000 个文件,但有时会在上传 26,000 个文件或有时会上传 27,000 个文件等后中断,并出现以下 PHP 警告,即

PHP Warning: ftp_put(): bind() failed: Address already in use (98)

我已经通过互联网研究了这个错误,但没有找到解决方案,因此,在此处发布。

我检查了目录号。具有 ext4 文件系统的 Ubuntu 14.0.4 LTS 服务器上的文件限制,并且找不到任何限制 33,000 个文件上传到单个目录的内容。

我尝试将相同的 33,000 个文件上传到两个不同的目录,即 20,000 个到 DirA,其余 13,000 个到 DirB,但是在 5,000 个成功文件传输到 DirB 后,它停止并出现上述错误。

这是我用来上传文件作为引用的基本代码,即

    $dpath = "/var/www/data/";
    $sourceDir = $dpath .'test1';
    $remoteDir = 'test2';

    $serverIp = "192.168.0.1";
    $user = "dataexport";
    $pass = "abc";

    $connHandle = ftp_connect($serverIp);
    if($connHandle)
    {
        $loginFlag = ftp_login($connHandle, $user, $pass) or   die('couldnt connect to $serverIp');

        if($loginFlag)
        {
            if(is_dir($sourceDir))
            {
                $dirHandle = opendir($sourceDir);

                if($dirHandle)
                {
                    while(($file = readdir($dirHandle)) !== false)
                    {
                        if($file != "." && $file != "..")
                        {
                            if(is_dir($sourceDir.'/'.$file))
                            {
                               // code for copying directory.. I am not using it.
                            }
                            else
                            {
                               $srcFilePath = $sourceDir.'/'.$file;
                               $desFilePath = $remoteDir.'/'.$file;

                                if(ftp_put($connHandle, $desFilePath, $srcFilePath, FTP_ASCII))
                                {
                                    echo "Copied Successfully to path: $desFilePath \n";
                                }
                                else 
                                {
                                    echo "Copying failed \n"; die();
                                }
                            }
                        }
                    }

                    closedir($dirHandle);
                }
            }
            else 
            {
                echo "Not a valid directory <br />\n";
            }
        }
        else
        {
            echo "Wrong Credentials for the server with IP = $loginFlag <br />\n";
        }
    }
    else 
    {
        echo "Unable to connect to server with IP = $serverIp <br />\n";
    }

    ftp_close($connHandle);
}

注意:我修改了我的真实代码以使其简单并且没有测试它可能需要一些测试......但是在成功传输 25,000 个文件后我在以下代码行中收到错误报告。即

ftp_put($connHandle, $desFilePath, $srcFilePath, FTP_ASCII)

我也尝试使用“FTP_BINARY”选项上传文件,但没有成功。

寻找您的任何好的解决方案建议。提前致谢。

干杯

最佳答案

错误信息解释得很清楚:

 bind() failed: Address already in use (98)

这与文件数量无关,也与传输模式无关。

原因深藏在 FTP 协议(protocol)的内部。 FTP 是一种旧协议(protocol),它使用命令连接和传输的每个文件使用新连接。每个 TCP 连接都绑定(bind)到 port ;端口号是一个 16 位无符号整数。这导致最多 64k 个可用端口。

前 1024 个端口号 (0..1023) 为众所周知的协议(protocol)保留(80 个用于 HTTP,25 个用于 SMTP,22 个用于 FTP命令连接等)。范围 1024..49151 包含“已注册”端口,49152 和 65535 之间的端口号包含“动态”端口。它们可供操作系统绑定(bind) short-lived connections给他们。 “动态”范围内有 16k 个端口号可用。

一些操作系统使用更大范围的动态端口。如 Wikipedia page 中所述):

Many Linux kernels use the port range 32768 to 61000.

此范围内大约有 28k 个可用端口。考虑到在您的脚本执行期间计算机上还有其他程序正在运行;其中许多创建 TCP 连接,这些连接也使用端口。这减少了应用程序可用的端口号数量。

我不知道 PHP 的 FTP 实现内部发生了什么,但看起来它并没有关闭它用于文件传输的数据连接,并且在数千个文件之后,整个库存应用程序可以使用的空闲端口被占用,系统调用 bind() 失败。

解决方案

由于显然没有办法在 PHP 中配置 FTP 函数的行为,您可以尝试关闭 FTP 连接并重新打开它。希望 PHP 将释放所有相关资源,包括它用于文件传输的许多端口。

这个我没查过,不知道行不行!

如果它不起作用,您可以尝试使用 ssh/sftp PHP 提供的函数。 SSH/SCP 是一种旨在避免旧协议(protocol)(如 FTP)的许多缺陷的协议(protocol)。您可以在函数 ssh2_scp_send() 的文档页面上找到基本用法示例.

关于PhP ftp_put 功能限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30927619/

相关文章:

php - Facebook SDK getAccessToken() 问题

php - 处理 PHP 多维数组以将键指定为值数组的父级

php - 排除 foreach 表中的列而不丢失数据

php - 如何知道某个元素可以在哪个页面找到?

PHP 无法更新 MySQL 但报告成功 - 在 phpmyadmin 中工作

php - 如何在 codeigniter 4 中自动加载辅助函数

javascript - 如果返回 false,如何在提交时关闭引导模式?

php - 使用菜单完成查询后,如何使下拉选择菜单持续显示相同的数据?

php - 带有 Action 的表单内具有不同目标的按钮

php - SQL 选择查询适用于 phpMyAdmin,但不显示任何 PHP Web 服务的输出