在FTP服务器上使用RETR时如何确定文件的结尾(PASV)

时间:2014-03-03 16:21:19

标签: c# sockets ftp

我决定在C#中推出自己的FTP Socket客户端,以便获得更多控制权,但主要是为了学习体验。但在发出RETR命令后,我无法弄清楚需要读取多少文件数据。我能够建立初始FTP通信连接,然后通过发出PASV命令和所有好东西在新端口上连接第二个套接字。

我的问题是,当我在通信端口上发出RETR命令时,FTP服务器开始通过Passive端口发送文件,然后在完成通信端口发送时发出226命令。我可以很好地接收数据,但有时226命令在所有文件数据到达被动端口之前到达通信端口。因此,如果我在获得226命令后立即通知我的Passive套接字任务停止读取,它有时会错过包含文件末尾的数据。我已经尝试在退出Socket.Receive循环之前检查Socket.Available但是通常Socket.Available会在套接字上报告0字节,但是套接字并不意味着没有&#39在途中有更多数据。阅读FTP规范似乎FTP服务器应该在完成发送所有数据后关闭数据连接,但我不认为这种情况正在发生。我可以整天循环读取0字节的数据。我是在看一个破损的FTP服务器,还是我在做方法上做错了什么?

现在有一些额外的信息可能是我的问题的答案。使用连接到同一FTP服务器的Filezilla,我看到在请求文件时,FTP服务器将文件长度附加到括号中的150命令。例如," 150打开test.zip(123421字节)的BINARY模式数据连接。"这个文本是FTP标准的一部分吗?如果所有FTP服务器使用相同的行为和格式,那么我可以继续阅读,直到我达到123,421字节。但如果这不是常见的行为,那么我回到原点。欣赏任何想法。

2 个答案:

答案 0 :(得分:0)

似乎我没有充分阅读规范,因为RFC 3659中有一个SIZE命令会返回文件的大小。我测试了它,它将完全符合我的需要。

答案 1 :(得分:0)

  

我无法弄清楚在发出RETR命令后我需要读取多少文件数据。

这取决于传输模式(参见RFC 959第3.4节)。

在STREAM模式(通常情况下)中,文件结尾由关闭数据套接字的发送方表示。这意味着数据连接不能重复用于多次传输。

在BLOCK模式下,数据以块的形式发送,发送方将在传输结束时发送EOF块。这允许数据连接重用于多次传输。

  

我的问题是,当我在通信端口上发出RETR命令时,FTP服务器开始通过Passive端口发送文件,然后在完成通信端口发送时发出226命令。我可以很好地接收数据,但有时226命令在所有文件数据到达被动端口之前到达通信端口。

在完成传输端口上的数据读取之前,只需读取通信端口上的响应即可。

  

因此,如果我在获得226命令后立即发出被动套接字任务信号以停止读取,则有时会错过包含文件末尾的数据。

所以不要发信号你的插座停止阅读。让它自己停止阅读。

  

我已经尝试在退出Socket.Receive循环之前检查Socket.Available但是通常Socket.Available会在套接字上报告0字节,但是套接字并不意味着没有更多途中的数据。

正确。 Available只是报告当时等待读取的字节数。只需继续阅读,直到Receive()告诉您实际发生断开连接。如果要在调用Receive()之前轮询套接字状态,请使用Poll(),断开连接将报告为可读状态。无论哪种方式,Receive()将在正常断开连接时返回0字节,并在异常断开连接时抛出异常。

  

阅读FTP规范似乎FTP服务器应该在完成发送所有数据后关闭数据连接

在STREAM模式下,是的。

  

但我不认为这种情况正在发生。

是的,是的。

  

我可以整天循环读取0字节的数据。我是在看一个破损的FTP服务器,还是我在做方法上做错了什么?

你的方法做错了。

  

使用连接到同一FTP服务器的Filezilla,我看到在请求文件时,FTP服务器将文件长度附加到括号中的150命令。例如,“150为test.zip打开BINARY模式数据连接(123421字节)。”这个文本是FTP标准的一部分吗?

不,不是。文本是任意的,它可以是服务器想要的任何东西。重要的是响应代码(150)表示转移正在进行。

  

如果所有FTP服务器都使用相同的行为和格式

他们不使用相同的文字格式。

  

然后我可以继续阅读,直到我达到123,421字节。

在服务器关闭数据连接之前,您应该继续阅读。然后在通信端口上读取最终响应,以确保服务器认为传输成功,而不是过早中止。