PhP ftp_put功能限制?

时间:2015-06-18 23:37:33

标签: php

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

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

  

PHP警告:ftp_put():bind()失败:地址已在使用中(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)

我尝试使用&#34; FTP_BINARY&#34;上传文件。选项,但没有工作。

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

干杯

2 个答案:

答案 0 :(得分:1)

错误信息非常明确:

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

这使得文件的数量无法解决,也与传输模式无关。

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

前面的1024个端口号(0..1023)是为众所周知的协议保留的(HTTP为80,SMTP为25,FTP命令连接为22,所以上)。范围1024..49151包含&#34;注册&#34;端口和49152和65535之间的端口号包含&#34;动态&#34;端口。它们可供操作系统将short-lived connections绑定到它们。 &#34;动态&#34;中有16k端口号可用。范围。

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

  

许多Linux内核使用32768到61000的端口范围。

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

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

解决方案

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

我没有检查过这个,我不知道它是否有效!

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

答案 1 :(得分:0)

可能发生的情况是,对于传输的每个文件,客户端在VPS上使用不同的本地端口。上传了数千个文件后,系统上的所有端口都在使用中。

您可以在VPS上运行netstat -anop以查看使用的端口。您可能需要调整net.ipv4.ip_local_port_range的值以增加可用端口的数量,并降低net.ipv4.tcp_fin_timeout值以更快地释放端口。

如果可能,您可以使用使用SSH的SFTP,并且不会有相同的端口使用限制。