我正在重新编码一个简单的 ftp 服务器,但我对 PASV 命令的实现感到困惑。
事实上,当客户端发送 PASV 命令时,我必须创建一个新的服务器套接字并将信息(地址和端口)发送回客户端,以便他可以连接到它以创建数据连接。
我一步一步做的是:
- 使用 INADDR_ANY 和随机端口(端口 0)创建服务器套接字
- 使用此套接字监听()
- getsockname() 这个套接字来获取它的信息
- 通过命令连接将信息发送回客户端
- 当用户需要使用数据连接时,accept() 会稍后完成
(这是正确的方法吗?)
问题是,我在服务器端创建的服务器套接字与 INADDR_ANY 绑定(bind),因此其上的 getsockname() 始终返回 0.0.0.0(因为它实际上绑定(bind)到系统外的所有 ip)。
这样的话,我应该发回什么地址给客户以及如何找到它?
真实的 ftp 服务器如何处理这个问题?
谢谢:)
最佳答案
What I do step by step is:
- Create a server socket with INADDR_ANY and random port (port 0)
- listen() with this socket
- getsockname() this socket to get it's infos
- send back the infos to the client on the command connection
- the accept() is done later, when the user need to use the data con
(Is that the right way to do it ?)
一般来说,是的,但是步骤 #1 和 #3 往往比这更复杂。
一方面,getsockname()
在套接字实际连接到某人之前无法获取真实 IP(在这种情况下,这意味着您必须在 getsockname()
返回的套接字上调用 accept()
,而不是在您调用 accept()
的套接字上) 。因此,当绑定(bind)到INADDR_ANY
时,您应该只报告命令套接字连接到的接口(interface)的 IP。在这种情况下,最好将监听套接字直接绑定(bind)到该接口(interface),而不是绑定(bind)到 INAADDR_ANY
完全没有。
另一件事,即使服务器计算机只安装了 1 个接口(interface),如果服务器位于 NAT 路由器后面,并且客户端位于 NAT 之外,那么您必须报告路由器的公共(public) IP,而不是服务器的监听知识产权。您必须提前知道路由器的公共(public) IP,方法是将其存储在应用程序的配置中,或者通过 uPNP 动态查询路由器本身,或者通过查询外部服务,如 http://iplookup.flashfxp.com/
。除非路由器支持 FTP(有些是)并且足够智能,可以在通过路由器时为您替换报告的 IP,在这种情况下,您必须报告您的监听 IP。
关于c - Socket,与INADDR_ANY绑定(bind)时如何查找本地地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44029454/