是否可以在套接字上取消监听?

时间:2020-03-06 15:01:16  来源:igfitidea点击:

调用listen(fd,backlog)后,是否可以取消监听套接字?

编辑:我的错误,因为我不能使自己清晰明了。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。我希望能够暂时取消监听套接字。调用close()将使套接字保持M2LS状态,并阻止我重新打开它(或者更糟糕的是,某些恶意程序可能会绑定到该套接字)

暂时取消监听是向上游负载平衡器发送信号的一种方式(也许不是最好的方式),该应用目前无法再接受任何请求

解决方案

关闭它。据我回忆;

close(fd);

没有明确的方法可以取消收听!

我们可以close(fd)或者shutdown(fd,how)

fd is the socket file descriptor you want to shutdown, and how is one of the following:

0 Further receives are disallowed

1 Further sends are disallowed

2 Further sends and receives are disallowed (like close())

关闭套接字后,程序可能仍会告诉我们套接字正在"使用中",这是由于我不完全了解某些怪异现象。但是有关套接字的联机帮助页显示有一个标记可以重复使用相同的套接字,即懒惰的名称:" SO_REUSEADDR"。使用" setsockopt()"进行设置。

从根本上讲,套接字是打开的还是关闭的(在这里,我们将忽略TCP / IP状态图的优点)。

如果套接字已关闭,则无法向其发送数据。如果它是打开的,则传入数据将被TCP / IP堆栈接受并确认,直到其缓冲算法发出"足够!"的声音为止。届时,将不再确认其他数据。

我可以看到两种选择。如果要"取消监听",请关闭套接字,然后再重新打开它。将带有SO_REUSEADDR标志的setsockopt()允许我们在TIME_WAIT2到期之前重新绑定到知名端口。

另一种选择是保持套接字打开,但在我们"忙"时根本不接受它。假设我们对请求有应用程序级的确认,那么负载均衡器将意识到它没有得到响应,因此将采取相应措施。

根据我们对问题的修改后的版本,我不确定我们是否必须"取消收听"或者close()。我想到两个选择:

1)在调用listen()之后,直到(逻辑上足够)调用accept(),连接才真正被接受。我们可以通过简单地忽略套接字活动并将所有accept()推迟到我们准备好它们之前来"取消监听"。任何入站连接尝试将积压到在侦听模式下打开端口时创建的队列。一旦堆栈中的积压队列已满,就可以将进一步的连接尝试简单地放在地板上。当我们使用accepts()恢复时,我们将迅速使待办事项退队,并准备进行更多连接。

2)如果我们确实希望端口暂时完全关闭,则可以将内核级别的数据包筛选器动态应用于该端口,以防止入站连接尝试到达网络堆栈。例如,我们可以在大多数* nix平台上使用Berkeley数据包过滤器(BPF)。也就是说,我们要使用平台的防火墙功能丢弃进入目标端口的入站数据包。当然,这会因平台而异,但这是一种可能的方法。

根据我们编辑的问题,这是一个非常丑陋的方法:

打开一个套接字以收听正常的积压。继续。

当我们想"关闭"时,打开一个积压为1和SO_REUSEADDR的第二个。关闭第一个。准备恢复时,请使用正常的待办事项对另一个套接字进行处理。

关于从要关闭的套接字中清空接受队列的挑剔细节将成为杀手here。可能足以使这种方法不可行的杀手er。

一些套接字库允许我们专门拒绝传入的连接。例如:GNU的CommonC ++:TCPsocket类具有拒绝方法。

BSD套接字没有此功能。我们可以接受连接,然后立即关闭它,同时保持套接字处于打开状态:

while (running) {

  int i32ConnectFD = accept(i32SocketFD, NULL, NULL);
  while (noConnectionsPlease) {
    shutdown(i32ConnectFD, 2);
    close(i32ConnectFD);
    break;
  }

}

我不一定认为这是个好主意,但是...

我们也许可以再次打电话听。 POSIX规范没有拒绝。想要"取消收听"时,可以使用积压参数0再次调用它。

似乎未定义实现,当积压为0的调用listen时会发生什么。 POSIX规范说它可能允许接受连接,这意味着如果backlog参数为0,则某些实现可能选择拒绝所有连接。不过,更可能的是,当我们传入0(可能为1或者)时,实现将选择一些正值。 SOMAXCONN)。

我认为这不是向上游负载均衡器发送信号的好方法。在通过这些连接获得的消息可能会被拒绝之前,它实际上必须向服务器发送一些连接。

同样,关闭侦听套接字时挂起的所有连接都将关闭,并且不包含任何数据。

如果要向上游负载均衡器发送信号,则应具有执行此操作的协议。不要尝试滥用TCP来做到这一点。

幸运的是,如果客户端是普通的Web浏览器,那么我们可以避免很多麻烦,只需关闭套接字通常会导致它们对用户透明地重试(一定程度上)。

问题没有说明哪种插座。如果它是unix套接字,则可以停止并开始使用rename(2)进行监听。我们还可以使用unlink(2)永久停止监听,并且由于套接字保持打开状态,因此我们可以继续为积压服务。这种方法似乎很方便,尽管我以前从未见过使用过它,而自己只是在探索它。