我可以在同一个套接字描述符上调用 bind() 然后 connect() 吗?

Posted

技术标签:

【中文标题】我可以在同一个套接字描述符上调用 bind() 然后 connect() 吗?【英文标题】:Can I call bind() and then connect() on same socket descriptor? 【发布时间】:2019-06-12 15:18:41 【问题描述】:

只是一个关于使用 C/C++ 在 Windows 应用程序中进行网络套接字编程的奇怪问题:

如何告诉connect() 函数使用特定的源 IP 和源端口值?

创建套接字后,应用程序使用sockaddr 结构调用connect() 到远程IP 和端口。

connect() 函数在内部为连接选择源 IP 和端口。

与其让系统决定 connect() 的源 IP 和/或端口,不如让应用程序负责决定绑定到哪个源 IP 和/或端口。

【问题讨论】:

"If socket s, is unbound, unique values are assigned to the local association by the system, and the socket is marked as bound." 如果您想指定使用哪个接口/端口组合,您需要调用bind "让应用程序负责决定要绑定的源端口或 IP" -- 请注意,尽管确实可能有理由将这种方法与您的套接字一起使用要去connect(),他们充其量是罕见的。这种连接的源端口通常在应用程序级别并不重要,并且源 IP 很少有很多选项(除非机器正在连接到自己)。 【参考方案1】:

bind() 请求未使用的端口,以便它可以声明它并成为服务器,而connect() 想要一个已经在使用的端口,因此它可以连接到它并与服务器通信。

正如用户 stark 所说,如果您想指定要使用的接口/端口组合,则需要调用 bind,尽管如果您希望下次调用将其绑定到随机可用端口号,您可以选择退出bind() 调用,因为客户端不一定必须具有固定的端口号。

在调用connect() 之前可以要求内核选择特定端口,但如果我可能会问 - 为什么你不想让内核分配源端口,据我所知这不是最佳实践。

【讨论】:

我想到了几个用例:可以将套接字绑定到接口而不绑定到端口(此处将在调用 connect 时选择端口。)。此外,在 P2P 网络中,需要在调用 connect 之前显式分配端口以启用 NAT 穿越。【参考方案2】:

如何告诉 connect() 函数使用特定的源 IP 和源端口值?

为此使用套接字库的bind() 函数。是的,您可以在connect() 之前调用bind() 以获得传出套接字。这对于 UDP 和 TCP 套接字都是完全合法的操作。

【讨论】:

【参考方案3】:

是的,你可以。 确实有这样做的理由:如果您的路由策略使您的连接从一个不是您想要使用的 IP 地址建立,您可以在多宿主/路由主机中强制通过bind(2) 系统调用将特定IP 地址作为源。另一个用途是为连接指定一个固定的源端口,但这不像以前的情况那样常见。

但请注意:您只能选择您拥有的已配置 IP 地址之一,而不是您可以想象的任何地址。

【讨论】:

以上是关于我可以在同一个套接字描述符上调用 bind() 然后 connect() 吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 C 中使用 bind() 时获取错误的 IP 地址

在进程退出时释放绑定端口

网络通讯中 bind函数的作用

C 读取和线程安全 (linux)

socket编程bind()函数

如何用c语言编写socket套接字