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

C 套接字,如何在与INADDR_ANY绑定时查找本地地址,c,sockets,server,ftp,C,Sockets,Server,Ftp,我正在重新编写一个简单的ftp服务器,我被PASV命令的实现卡住了 事实上,当客户端发送PASV命令时,我必须创建一个新的服务器套接字,并将INFO(地址和端口)发送回客户端,以便客户端可以连接到它来创建数据连接 我一步一步做的是: 创建具有INADDR_ANY和随机端口(端口0)的服务器套接字 使用此套接字侦听() getsockname()使用此套接字获取其信息 通过命令连接将信息发送回客户端 accept()稍后在用户需要使用数据时完成 (这样做对吗?) 问题是,我在服务器端创建的服务器套

我正在重新编写一个简单的ftp服务器,我被PASV命令的实现卡住了

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

我一步一步做的是:

  • 创建具有INADDR_ANY和随机端口(端口0)的服务器套接字
  • 使用此套接字侦听()
  • getsockname()使用此套接字获取其信息
  • 通过命令连接将信息发送回客户端
  • accept()稍后在用户需要使用数据时完成
  • (这样做对吗?)

    问题是,我在服务器端创建的服务器套接字绑定了INADDR_ANY so getsockname(),它总是返回0.0.0.0(因为它绑定到系统之外的几乎所有IP)

    如果是这样的话,我应该将什么地址发送回客户,以及如何找到它

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

    谢谢:)

    我一步一步做的是:

  • 创建具有INADDR_ANY和随机端口(端口0)的服务器套接字
  • 使用此套接字侦听()
  • getsockname()使用此套接字获取其信息
  • 通过命令连接将信息发送回客户端
  • accept()稍后在用户需要使用数据时完成
  • (这样做对吗?)

    一般来说,是的,但是步骤1和步骤3往往比这更复杂

    首先,
    getsockname()
    在套接字实际连接到某人之前无法获得真正的IP(在本例中,这意味着您必须在
    accept()
    返回的套接字上调用
    getsockname()
    ,而不是在调用
    accept()
    的套接字上调用)。因此,当绑定到INADR\u ANY时,您应该只报告命令套接字所连接的接口的IP。在这种情况下,最好只将侦听套接字直接绑定到该接口,而不直接绑定到添加的
    inaddr\u ANY


    另一方面,即使服务器机器只安装了1个接口,如果服务器位于NAT路由器后面,而客户端位于NAT之外,那么您也必须报告路由器的公共IP,而不是服务器的侦听IP。您必须提前知道路由器的公共IP,或者将其存储在应用程序的配置中,或者通过uPNP动态查询路由器本身,或者通过查询外部服务(如
    http://iplookup.flashfxp.com/
    。除非路由器能够识别FTP(有些是),并且足够聪明,可以在通过路由器时为您替换报告的IP,否则您必须报告您的侦听IP。

    您应该在命令套接字上调用
    getsockname()
    。这将为您提供客户端用于连接到您的IP地址。对于多主机主机上的每个客户端,它可能是不同的。如果您在NAT设备后面,您应该使用其公共IP地址,您必须通过配置获得该地址。

    您知道当前FTP连接使用的是哪个本地接口。绑定到该接口(使用随机端口)。像现在这样绑定到
    INADDR\u ANY
    应该可以工作。但是,只绑定到客户端正在使用的地址会更干净。我认为您可以通过在连接的套接字(用于命令连接)上使用
    getsockname()
    来实现这一点而不是在侦听套接字上。@Someprogrammerdude我如何知道我当前的FTP连接使用的是哪个接口?@JohnBollinger所以我在这里只是获取sockname命令连接套接字并保存addr并用我的数据连接套接字绑定到它?这些地址总是相同的?@JohnBollinger:“当客户端试图建立数据连接时,它将尝试连接到它已经建立命令连接的同一台机器”——根据FTP规范,客户端应该连接到服务器所说的任何IP,可以是服务器想要的任何IP,即使是一台换另一台机器,如果它愿意的话。实际上,FTP客户机通常可以选择忽略服务器的指定IP,而只使用已经连接的IP,这通常是好的。