套接字,如何在与INADDR_ANY绑定时找到本地地址

时间:2017-05-17 15:45:48

标签: c sockets server ftp

我正在重新编码一个简单的ftp服务器,而且我对PASV命令的实现感到困惑。

实际上,当客户端发送PASV命令时,我必须创建一个新的服务器套接字并将信息(地址和端口)发送回客户端,以便他可以连接到它以创建数据连接。

我一步一步做的是:

  1. 使用INADDR_ANY和随机端口(端口0)
  2. 创建服务器套接字
  3. listen()使用此套接字
  4. getsockname()这个套接字来获取它的信息
  5. 通过命令连接
  6. 将信息发送回客户端
  7. 当用户需要使用数据con
  8. 时,accept()将在稍后完成

    (这是正确的方法吗?)

    问题是,我在服务器端创建的服务器套接字与INADDR_ANY捆绑在一起,因此它上面的getsockname()总是返回0.0.0.0(因为它几乎绑定到系统中的所有ips)。

    是那种情况,我应该将哪个地址发回客户端以及如何找到它?

    真正的ftp服务器如何处理这个问题?

    谢谢:)

2 个答案:

答案 0 :(得分:0)

  

我一步一步做的是:

     
      
  1. 使用INADDR_ANY和随机端口(端口0)
  2. 创建服务器套接字   
  3. listen()使用此套接字
  4.   
  5. getsockname()这个套接字来获取它的信息
  6.   
  7. 通过命令连接
  8. 将信息发送回客户端   
  9. 当用户需要使用数据con
  10. 时,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地址,您必须通过配置获取该地址。