我可以将同一个套接字用于多个连接吗?

Posted

技术标签:

【中文标题】我可以将同一个套接字用于多个连接吗?【英文标题】:Can I use the same socket for multiple connections? 【发布时间】:2018-01-09 00:42:02 【问题描述】:

我正在尝试制作一个扫描一系列地址的 python 函数。我启动了一个套接字并将套接字作为参数传递给连接到它的函数:

def scan(socket, address, port):
    c = socket.connect_ex((address, port))
    print(c)

然后我为每个地址调用scan,每个地址都在自己的线程中。我收到了Error 114: Operation already in progress.

我需要为每个连接启动一个新的套接字吗?我正在尝试阅读有关套接字重用的信息,我发现存在 SO_ADDREUSE 之类的标志或类似的东西。我尝试插入,但没有成功。

我正在尝试思考套接字是如何工作的。我想当我创建一个时,它选择了一个 tcp 源端口,然后当我创建一个连接时,它发送到一个目标端口。我认为我不能重用同一个套接字,因为源端口对于所有目标端口都是相同的,所以客户端会响应同一个端口并会引起混淆。

那么我需要为每个连接创建一个新的套接字吗?

【问题讨论】:

阅读ALP & socket(7) & ip(7) & tcp(7) 【参考方案1】:

我需要为每个连接启动一个新的套接字吗?

是的。

我正在尝试阅读有关套接字重用的信息

没有“套接字重用”之类的东西。有 port 重用。不是一回事。一旦尝试连接现有套接字,即使连接尝试失败,您也无法重新连接它。

我发现存在 SO_ADDREUSE 之类的标志或类似的东西

SO_REUSEADDR 表示重用端口。不是插座。

【讨论】:

【参考方案2】:

我正在尝试思考套接字是如何工作的。我想我创建一个的那一刻,它选择了一个 tcp 源端口,

在使用socket() 系统调用创建套接字和使用它通过connect() 系统调用创建传出连接之间,可以选择使用bind() 系统调用来设置源IP 地址和/或端口,如果你想。如果不使用bind(),当你使用connect()系统调用时,操作系统会自动将socket绑定到合适范围内的第一个可用端口。在这种情况下,通常选择源 IP 地址来匹配根据路由表提供到指定目的地的最短路由的网络接口。

至少,它在系统调用级别是这样工作的。一些编程语言或库可能会选择将其中一些操作合并为一个。

对于您的实际问题,man 7 ip 说:

已绑定的 TCP 本地套接字地址对某些人不可用 关闭后的时间,除非设置了 SO_REUSEADDR 标志。关心 使用此标志时应采取此标志,因为它会降低 TCP 的可靠性。

这个想法是延迟端口的重用,直到属于关闭连接的任何可能重新发送的包副本在网络上肯定过期。

根据bind() 手册页,尝试重新绑定已经绑定到地址的套接字将导致 EINVAL 错误。因此,使用bind(socket, INADDR_ANY, 0)(在结束使用 SO_REUSEADDR 的连接之后)“回收”套接字似乎是不可能的。

即使这是可能的,当您在现代多核系统上使用多个线程时,您最终(很可能)会并行执行多项操作。一个套接字一次只能用于一个传出连接。您的每个scan 线程都需要自己的套接字。

【讨论】:

我认为SO_REUSEADDR 是关于重用 TCP/IP 地址,而不是作为系统构造的套接字。 没有“套接字的重用”之类的东西。您将不存在的套接字重用与确实存在的端口重用混淆了。 呃!我试图指出这一点,但在一个重要的句子中脑残。固定。

以上是关于我可以将同一个套接字用于多个连接吗?的主要内容,如果未能解决你的问题,请参考以下文章

套接字连接可以多路复用吗?

Java 可以并行运行同一个套接字的多个实例吗?

具有多个套接字连接的 HTTP2 和 TLS

可以将 socket.io 用于域套接字吗?

用于连接数据库的 Jdbc 连接与套接字连接 [关闭]

建立多个连接时如何在C中设置套接字超时?