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

时间:2008-10-02 11:37:00

标签: linux posix sockets listen

调用listen(fd,backlog)后,是否可以在套接字上取消删除?

编辑:我没有弄清楚自己的错误。我希望能够暂时解除套接字的问题。调用close()会使套接字处于M2LS状态并阻止我重新打开它(或者更糟糕的是,某些恶意程序可以绑定到该套接字)

暂时取消隐藏将是向上游负载均衡器发出信号的一种方式(可能不是最佳方式)此应用暂时无法接受任何更多请求

11 个答案:

答案 0 :(得分:5)

关闭套接字后,你的程序可能仍然告诉你套接字“正在使用”,这是因为我不确切知道一些奇怪的问题。但是有关套接字的联机帮助页显示,有一个标志可以重用同一个套接字,懒得称之为:“SO_REUSEADDR”。使用“setsockopt()”设置它。

答案 1 :(得分:4)

关闭它。我记得;

close(fd);

答案 2 :(得分:4)

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

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

while (running) {

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

}

答案 3 :(得分:2)

根据您编辑的问题版本,我不确定您是否必须“取消”或关闭()。我想到了两个选择:

1)在调用listen()之后,实际上不会接受连接,直到(逻辑上足够)调用accept()。您可以通过简单地忽略套接字活动并推迟任何accept()来“取消”,直到您为它们做好准备。任何入站连接都会尝试积压到在侦听模式下打开端口时创建的队列。一旦堆栈中的积压队列已满,就会在地板上放下进一步的连接尝试。当您使用accepts()恢复时,您将快速将待办事项出列,并为更多连接做好准备。

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

答案 4 :(得分:2)

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

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

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

幸运的是,如果客户端是普通的Web浏览器,那么您可以侥幸逃脱 - 只需关闭套接字通常会导致它们对用户透明地重试(到某一点)。

答案 5 :(得分:1)

没有明确的方法可以解开!

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

答案 6 :(得分:0)

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

如果您的套接字已关闭,则没有任何内容可以向其发送数据。如果它是打开的,那么TCP / IP堆栈将接受并确认传入的数据,直到它的缓冲算法“足够!”。此时,将不会确认更多数据。

我可以看到两个选择。当你想要“unlisten”时关闭()套接字,并在以后重新打开它 - 使用带有SO_REUSEADDR标志的setsockopt()允许你在TIME_WAIT2到期之前重新绑定到众所周知的端口。

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

答案 7 :(得分:0)

根据您编辑的问题,这是一种相当丑陋的方法:

使用正常的待办事项打开一个用于收听的套接字。继续进行。

如果要“关闭”,请打开积压为1且SO_REUSEADDR的第二个。关闭第一个。准备好恢复时,再做另一个套接字与一个正常积压的套接字。

从你正在关闭的套接字中排出接受队列的挑剔细节将成为杀手。可能足以让这种方法无法实现。

答案 8 :(得分:0)

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

您可以第二次拨打电话。 POSIX规范没有说不。当你想要“unlisten”时,也许你可以第二次用backlog参数0来调用它。

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

答案 9 :(得分:0)

问题没有说出什么样的套接字。如果是unix套接字,则可以使用rename(2)停止并开始监听。您还可以使用unlink(2)永久停止侦听,并且由于套接字保持打开状态,您可以继续为待办事项提供服务。这种方法看起来很方便,虽然我之前没有看过,我只是自己探索它。

答案 10 :(得分:0)

您已经通过套接字API获得了无法做到这一点的答案。

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

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

无论如何,如果您受到检测到不可用性的探测的限制,您可以设置一个应用程序级别探测器来执行HTTP请求或FTP登录,或者如果您在接受后只是关闭它将识别它们。它甚至可以解释像“500 service not available”这样的错误消息,这对我来说似乎更干净。使用SNMP,某些负载均衡器也可以将结果用作加载提示。