在TCP三次握手之前获取INADDR_ANY客户端套接字的源IP和端口?

时间:2015-03-29 16:30:55

标签: sockets tcp winsock winsock2

我在Windows 7上,bind之前使用connect SO_REUSEADDR,并将本地地址结构设置为IP地址INADDR _ANY和端口0(零),以便让操作系统选择客户端套接字的源详细信息。

首先,我已经读过在连接到服务器之前无法获取源IP,因为此时正在选择它并且几个地址可以有效。但是在连接之前选择了端口,那么有没有办法获得它? (getsockname()看起来不起作用。)

其次,关于源IP,有没有办法在将数据包发送到服务器之前获取它?我需要在OS选择源IP的那一刻和它开始三次握手的那一刻之间的特定时间。 connect()函数支配两者。

2 个答案:

答案 0 :(得分:1)

  

我在Windows 7上使用bind之前使用connect SO_REUSEADDR

为什么在这种情况下使用SO_REUSEADDR?你不需要它,它对你正在尝试的东西毫无意义。 SO_REUSEADDR通常只能用于收听套接字,而不能用于连接套接字。

  

将本地地址结构设置为IP地址INADDR _ANY和端口0(零),以便让操作系统选择客户端套接字的源详细信息。

bind()的{​​{1>} 客户端套接字没有意义。您可以(并且应该)完全省略这样的INADDR_ANY:0并保留套接字未绑定,直到调用bind()为止。 connect() 客户端套接字的时间是否要将其绑定到特定的 em>本地IP和/或端口。但是你不是在这种情况下这样做,所以摆脱它。

  

首先,我已经读过在连接到服务器之前无法获取源IP,因为此时正在选择它并且有几个地址可以有效。

更正,除非您bind()指向特定的源IP。

  

但是在连接之前选择了端口

如果套接字未绑定,或者绑定到源IP bind()和/或源端口0,则connect()选择源IP和源端口。因此,您没有机会查询任何一个值INADDR_ANY选择了它们。

  

有没有办法得到它? (connect()看起来不起作用。)

getsockname()正是您所需要的。只需确保在getsockname()成功连接到服务器之前才调用它。这在getsockname()文档中说明:

  

在没有先执行绑定的情况下进行连接调用时,此调用特别有用; getsockname函数提供了确定系统已设置的本地关联的唯一方法。
  ...
  当套接字绑定到未指定的地址时,getsockname函数并不总是返回有关主机地址的信息,除非套接字已连接到connect或accept(例如,使用ADDR_ANY)。 Windows套接字应用程序不得假定将指定地址,除非套接字已连接。除非在多宿主主机中使用套接字,否则将用于套接字的地址是未知的。如果套接字使用无连接协议,则在套接字上发生I / O之前,该地址可能不可用。

  

其次,关于源IP,有没有办法在数据包发送到服务器之前获取它?

对于TCP,您可以在connect()成功连接到服务器后立即使用getsockname()检索所选的源IP。不是之前。

  

我需要从OS选择源IP到启动三次握手的那一刻之间的特定时间。

无法确定细节。没有套接字应用程序应该需要这个细节。你为什么需要它?

答案 1 :(得分:0)

  

我在Windows 7上,在连接SO_REUSEADDR之前使用bind,并将本地地址结构设置为IP地址INADDR _ANY和端口0(零),以便让操作系统选择客户端套接字的源详细信息

为什么呢?如果你根本没有调用bind()会发生这种情况,在connect().期间将客户端套接字绑定到INADDR_ANY在任何情况下都是不正确的。如果不指定非零端口号,则设置SO_REUSEADDR没有意义。只需删除所有这些。

  

首先,我已经读过在连接到服务器之前无法获取源IP,因为此时正在选择它并且有几个地址可以有效。

正确。

  

但是在连接之前选择了端口,那么有没有办法获得它呢?

是。 getsockname().

  

(getsockname()看起来不起作用)

不起作用?

  

其次,关于源IP,有没有办法在数据包发送到服务器之前获取它?

只要getsockname()成功,您就可以使用connect()获取它,但这涉及将数据包发送到服务器。

  

我需要从操作系统选择源IP到启动三次握手的那一刻之间的特定时间。 connect()函数支配两者。

运气不好。