我正在重新编码一个简单的ftp服务器,而且我对PASV命令的实现感到困惑。
实际上,当客户端发送PASV命令时,我必须创建一个新的服务器套接字并将信息(地址和端口)发送回客户端,以便他可以连接到它以创建数据连接。
我一步一步做的是:
(这是正确的方法吗?)
问题是,我在服务器端创建的服务器套接字与INADDR_ANY捆绑在一起,因此它上面的getsockname()总是返回0.0.0.0(因为它几乎绑定到系统中的所有ips)。
是那种情况,我应该将哪个地址发回客户端以及如何找到它?
真正的ftp服务器如何处理这个问题?
谢谢:)
答案 0 :(得分:0)
我一步一步做的是:
- 使用INADDR_ANY和随机端口(端口0)
创建服务器套接字- listen()使用此套接字
- getsockname()这个套接字来获取它的信息
- 通过命令连接
将信息发送回客户端- 当用户需要使用数据con
时,accept()将在稍后完成 醇>(这是正确的方法吗?)
一般情况下,是的,但步骤#1和#3往往比这更复杂。
首先,getsockname()
无法获得真正的IP,直到套接字实际连接到某人(在这种情况下,这意味着您必须在{{}返回的套接字上调用getsockname()
1}},而不是在你调用accept()
的套接字上)。因此,绑定到accept()
时,您应该只报告命令套接字所连接的接口的IP。在这种情况下,最好只将侦听套接字直接绑定到该接口,而不是INADDR_ANY
。
另外,即使服务器机器只安装了1个接口,如果服务器位于NAT路由器后面,并且客户端在NAT之外,那么你必须报告路由器的公共IP您的服务器的监听IP。您必须提前知道路由器的公共IP,方法是将其存储在应用程序的配置中,或者通过uPNP动态查询路由器本身,或者查询外部服务,如{{1 }}。除非路由器支持FTP(有些是)并且足够智能,以便在通过路由器时替换报告的IP,在这种情况下,您必须报告您的侦听IP。
答案 1 :(得分:0)
您应该在命令套接字上调用{{1}}。这为您提供了客户端用于连接到您的IP地址。对于多宿主主机上的每个客户端,它可以是不同的。如果您在NAT设备后面,则应使用其公共IP地址,您必须通过配置获取该地址。