可以打开插座吗



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

编辑:我的错误是没有把自己说清楚。我希望能暂时打开插座。调用close()将使套接字处于M2LS状态,并阻止我重新打开它(或者更糟的是,一些邪恶的程序可能会绑定到该套接字)

暂时取消绑定是向上游负载均衡器发出信号的一种方式(可能不是最好的方式),表明该应用程序暂时无法接受任何请求。

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

BSD套接字没有这个功能。您可以接受连接,然后立即关闭,同时保持套接字打开:

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

关闭套接字后,您的程序可能仍然会告诉您套接字"正在使用",这是因为我不太清楚的一些奇怪之处。但是,关于套接字的手册页显示,有一个可以重复使用同一套接字的标志,懒洋洋地称为:"SO_REUSEADDR"。使用"setsockopt()"进行设置。

关闭它。我记得;

close(fd);

根据您编辑的问题版本,我不确定您是否必须"取消收听"或关闭()。脑海中浮现出两个选项:

1) 在调用list()之后,直到(从逻辑上讲)调用accept(),连接才真正被接受。您可以通过简单地忽略套接字活动并推迟任何accept(),直到您准备好它们来"取消侦听"。任何入站连接都会尝试囤积到在侦听模式下打开端口时创建的队列中。一旦堆栈中的积压工作队列已满,则只需将进一步的连接尝试放到地板上即可。当您继续使用accepts()时,您将很快将积压工作排成队列,并为更多的连接做好准备。

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

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

同样,关闭侦听套接字时挂起的任何连接都将在没有数据的情况下关闭。

如果你想向上游负载均衡器发出信号,你应该有一个这样做的协议。不要试图滥用TCP来做这件事。

幸运的是,如果客户端是普通的web浏览器,你可以逃脱很多惩罚——简单地关闭套接字通常会导致它们对用户透明地重试(在一定程度上)。

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

您可以选择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())

在基本级别上,套接字要么打开,要么关闭(我们将忽略TCP/IP状态图的细节)。

如果你的套接字是关闭的,那么没有什么可以向它发送数据。如果它是打开的,那么传入的数据将被TCP/IP堆栈接受和确认,直到它的缓冲算法大喊"够了!"。届时,进一步的数据将不会得到确认。

我能看到你有两个选择。当您想"取消侦听"时,请关闭()套接字,稍后再重新打开它-使用带有SO_REUSEADDR标志的setsockopt(),允许您在TIME_WAIT2过期之前重新绑定到已知端口。

另一种选择是保持套接字打开,但在"忙"时不接受它的()。假设您有一个应用程序级别的请求确认,负载均衡器就会意识到它没有得到响应,并采取相应的行动。

根据您编辑的问题,这里有一个相当丑陋的方法:

打开一个套接字以使用正常的囤积进行侦听。继续

当你想"关闭"时,打开第二个积压为1和SO_REUSEADDR的。关闭第一个。当准备好恢复时,再做一个套接字杂耍到一个有正常积压的套接字。

从正在关闭的套接字中排出接受队列的挑剔细节将是这里的杀手。可能是一个足以让这种方法失效的杀手。

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

你也许可以再叫一次"听"。POSIX规范并没有说不可以。也许当你想"unlisten"时,你可以用backlog参数0再次调用它。

当使用0的backlog调用listen时,会发生什么似乎是由实现定义的。POSIX规范表示,它可以允许接受连接,这意味着如果backlog参数为0,一些实现可能会选择拒绝所有连接。更可能的是,当您传入0时,您的实现将选择一些正值(可能是1或SOMAXCONN)。

问题没有说明什么类型的套接字。如果是unix套接字,则可以使用rename(2)停止并开始侦听。您还可以使用unlink(2)永久停止侦听,并且由于套接字保持打开状态,您可以继续为积压工作提供服务。这种方法似乎很方便,尽管我以前从未见过这种方法,只是自己在探索。

您已经得到了一些关于通过套接字API不可能做到这一点的答案。

您可以使用其他操作系统方法(即Host firwewall/itables/ipfilter)来设置临时拒绝规则。

我发现大多数负载均衡器识别连接问题的可能性有点有限(大多数负载均衡器只在连接探针中识别RST,而不是作为合法连接尝试的答案。)

无论如何,如果您受到检测不可用性的探测器的限制,您可以设置一个应用程序级探测器,它可以执行HTTP请求或FTP登录或类似的事情,如果您在接受后简单地关闭,它就会识别这些事情。它甚至可以解释像"500服务不可用"这样的错误消息,这对我来说似乎更干净。使用SNMP,一些负载均衡器也可以将结果用作负载提示。

相关内容

  • 没有找到相关文章

最新更新