【问题标题】:How to implement reaction to EPSV (ALL) command in my FTP server?如何在我的 FTP 服务器中实现对 EPSV (ALL) 命令的响应?
【发布时间】:2019-04-25 19:59:41
【问题描述】:

我正在尝试通过 Wi-Fi 在我的本地网络上用 Java 设置 FTP 服务器。而且我坚持处理EPSV ALL 命令。作为客户,我在 iPhone 上使用 VLC 播放器。当我尝试播放 .mp4 文件时,它正在向服务器发送EPSV ALL。此行的服务器响应:

"229 Entering Extended Passive Mode (|||" + freeDataPort + "|)"

服务器在freeDataPort 上创建serverSocket,监听收入连接,没有任何反应。

我已经尝试通过连接到 FileZilla 服务器打开电影 - 它可以正常工作。我也无法理解为什么客户端在此命令(EPSV)之后尝试建立第二个连接(请求用户并再次传递的连接),而PASV 命令创建数据连接并进行简单的数据传输,例如响应LIST ,在第一个处理。

这是我使用的EPSV 的处理程序:

private void handleEpsv() {
    sendMsgToClient("229 Entering Extended Passive Mode (|||" + freeDataPort + "|)");
    try {
        dataSocket = new ServerSocket(freeDataPort);
        System.out.println("waiting for connect... port: " + freeDataPort);
        dataConnection = dataSocket.accept();
        dataOutWriter = new PrintWriter(dataConnection.getOutputStream(), true);
    } catch (IOException e)
    {
        debugOutput("Could not create data connection.");
        e.printStackTrace();
    }
}

最后的结果:

FTP Server started listening on port 21
{/192.168.0.105=INITIALThread-0    Threads in data list: 0}
New connection received. Worker was created.
from INITIAL THREAD
Thread-0 - send to client:    220 Welcome to the FTP-Server

USER a from INITIAL THREAD
Thread-0 - send to client:    331 User name okay, need password

PASS a from INITIAL THREAD
Thread-0 - send to client:    230 User logged in successfully

SYST from INITIAL THREAD
Thread-0 - send to client:    215 UNIX Type: L8

PWD from INITIAL THREAD
Thread-0 - send to client:    257 "/"

TYPE I from INITIAL THREAD
Thread-0 - send to client:    200 OK

CWD // from INITIAL THREAD
Thread-0 - send to client:    250 CWD successful. / is current directory

PASV from INITIAL THREAD
Thread-0 - send to client:    227 Entering Passive Mode (192,168,0,199,7,232)

waiting for connect... port: 2024
Data connection - Passive Mode - established
LIST from INITIAL THREAD
Thread-0 - send to client:    125 Opening ASCII mode data connection for file list.

from INITIAL THREAD
Thread-0 - send to client:    226 Transfer complete.

{/192.168.0.105=INITIALThread-0    Threads in data list: 1}
New connection received. Worker was created.

Thread-1 - send to client:    220 Welcome to the FTP-Server

FEAT 
Thread-1 - send to client:    211-Features:


Thread-1 - send to client:    MDTM


Thread-1 - send to client:    REST STREAM


Thread-1 - send to client:    SIZE


Thread-1 - send to client:    MLST type*;size*;modify*;


Thread-1 - send to client:    MLSD


Thread-1 - send to client:    UTF8


Thread-1 - send to client:    CLNT


Thread-1 - send to client:    MFMT


Thread-1 - send to client:    EPSV


Thread-1 - send to client:    EPRT


Thread-1 - send to client:    211 END

USER a 
Thread-1 - send to client:    331 User name okay, need password

PASS a 
Thread-1 - send to client:    230 User logged in successfully

EPSV ALL 
Thread-1 - send to client:    229 Entering Extended Passive Mode (|||2025|)

used by Thread-1 Thread DATA type
waiting for connect... port: 2025

【问题讨论】:

    标签: java sockets ftp


    【解决方案1】:

    EPSV ALL 不是EPSVEPSV ALL 有特殊含义。客户端使用它来表明它只会使用EPSV,而不是PASVPORTEPRT。您应该只回复 200 OK 之类的内容。你应该阅读RFC 2428

    实际上,我从未见过任何使用此命令的 FTP 客户端。大多数服务器会忽略它或错误地处理它。 VLC 无法与您的服务器通信的原因可能是除了响应不正确之外,您还阻止了您的控制连接等待传入的数据传输。并且 VLC 正在发送更多命令并超时等待您的服务器响应(因此它可能会通过打开新连接来重试)。

    这是 VLC 连接到 FileZilla FTP 服务器的脚本。请注意,FileZilla 也会错误地处理 EPSV ALL,通过回复 229 Entering Extended Passive Mode。但不会阻塞控制连接,正确处理以下命令(包括后面的EPSV)。

    230 Logged on
    EPSV ALL
    229 Entering Extended Passive Mode (|||65079|)
    TYPE I
    200 Type set to I
    SIZE video.avi
    213 119035510
    EPSV
    229 Entering Extended Passive Mode (|||63465|)
    TYPE I
    200 Type set to I
    RETR video.avi
    150 Opening data channel for file download from server of "/video.avi"
    ...
    

    实际上即使命令是普通的EPSV,你也不应该阻塞控制连接,因为客户端会发送更多的命令,尤其是RETR(或STORLISTMLSD ...)。

    【讨论】:

    • 成功了,谢谢!事实证明,如果你想获得视频流,VLC 播放器希望你创建三个不同的线程,而我阻止了第二个。
    • @RomanFrolov 附带说明一下,在响应 PASV 或 EPSV 进行实际传输时,在侦听端口实际打开并首先侦听之前,不要将回复发送给客户端。如果端口无法打开,则改为发送失败回复。你的handleEpsv() 没有做这些。一旦客户端收到成功回复,它会尝试连接,如果您实际上还没有打开端口,则会失败
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多