代码之家  ›  专栏  ›  技术社区  ›  Dave Cheney

有没有可能在插座上不听话?

  •  13
  • Dave Cheney  · 技术社区  · 17 年前

    编辑:我的错误是没有说清楚。我希望能够暂时取消对插座的收听。调用close()将使套接字保持M2LS状态,并阻止我重新打开它(或者更糟的是,某些恶意程序可能会绑定到该套接字)

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

    11 回复  |  直到 17 年前
        1
  •  5
  •   gx.    17 年前

        2
  •  4
  •   RickyA    10 年前

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

    BSD套接字没有此功能。你可以 接受 在保持插座打开的同时:

    while (running) {
    
      int i32ConnectFD = accept(i32SocketFD, NULL, NULL);
      while (noConnectionsPlease) {
        shutdown(i32ConnectFD, 2);
        close(i32ConnectFD);
        break;
      }
    
    }
    
        3
  •  4
  •   Matthew Scharley    17 年前

    close(fd);
    
        4
  •  2
  •   Tall Jeff    17 年前

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

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

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

        5
  •  2
  •   MarkR    16 年前

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

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

    如果您想要向上游负载平衡器发送信号,那么您应该有一个协议来实现这一点。不要试图滥用TCP来做这件事。

    幸运的是,如果客户端是普通的web浏览器,那么您可以侥幸逃脱很多麻烦——简单地关闭套接字通常会导致它们对用户透明地重试(在某种程度上)。

        6
  •  1
  •   prakash    17 年前

    没有显式的方法来取消听!

    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())
    
        7
  •  0
  •   Roddy    17 年前

    如果套接字已关闭,则任何内容都无法向其发送数据。如果它是打开的,那么传入的数据将被TCP/IP堆栈接受和确认,直到它的缓冲算法喊“够了!”。届时,将不会确认进一步的数据。

    我可以看到你有两个选择。如果要“取消侦听”,请关闭()套接字,稍后再重新打开它-使用带有SO_REUSEADDR标志的setsockopt(),以便在等待2过期之前重新绑定到已知端口。

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

        8
  •  0
  •   Darron    17 年前

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

    打开一个套接字,以便使用正常的待办事项进行侦听。继续

    关于从要关闭的套接字中排出接受队列的挑剔细节将是这里的杀手。很可能是一个足以让这种方法不可行的杀手。

        9
  •  0
  •   Dan    17 年前

    你也许可以第二次打电话给listen。POSIX规范没有说不要。当您想要“取消侦听”时,也许可以使用backlog参数0再次调用它。

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

        10
  •  0
  •   Andrew    15 年前

        11
  •  0
  •   eckes    14 年前

    您已经得到了一些关于不可能通过socket API实现这一点的答案。

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

    推荐文章