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



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

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

然后我为每个地址调用scan,每个地址都有自己的线程。我越来越Error 114: Operation already in progress..

我是否需要为每个连接启动一个新套接字?我正在尝试阅读有关套接字重用的信息,我发现存在像SO_ADDREUSE之类的标志。我试图插入,但没有用。

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

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

您不能多次连接stream套接字。

connect可能的错误之一是EISCONN.

插座已连接。

这适用于流套接字。

man bind也有这个:

[EINVAL] 套接字已绑定到地址,并且 协议不支持绑定到新地址;或 套接字已关闭。

同样,这适用于stream套接字。

man connect

通常,流套接字只能成功连接()一次;数据报套接字可以多次使用 connect()来更改其关联。

我强调了重要的路线。

stream插座不能多次连接。datagram插座可以多次连接。一般来说,BSD sockets有多个协议、类型和域可用。您应阅读针对您的特定情况的文档。

附言 熟悉问题评论中建议的阅读材料。这将足以解释操作套接字系列的函数。

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

是的。

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

没有"套接字重用"这样的东西。有端口重用。不是一回事。尝试连接现有套接字后,即使连接尝试失败,也无法重新连接。

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

SO_REUSEADDR意味着重用端口。不是插座。

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

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

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

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

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

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

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

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

最新更新