Linux 中的正常关闭服务器套接字

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9681531/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 05:08:17  来源:igfitidea点击:

Graceful Shutdown Server Socket in Linux

clinuxtcp

提问by benmmurphy

I want to be able to stop listening on a server socket in linux and ensure that all connections that are open from a client's point of view are correctly handled and not abruptly closed (ie: receive ECONNRESET).

我希望能够停止侦听 linux 中的服务器套接字,并确保正确处理从客户端的角度打开的所有连接,而不是突然关闭(即:接收 ECONNRESET)。

ie:

IE:

sock = create_socket();
listen(sock, non_zero_backlog);
graceful_close(sock);

if thought calling close() and handling already accept'd sockets would be enough but there can be connections that are open in the kernel backlog which will be abruptly closed if you call close() on the server socket.

如果认为调用 close() 并处理已经接受的套接字就足够了,但是内核积压中可能存在打开的连接,如果您在服务器套接字上调用 close() 则会突然关闭。

采纳答案by Gil

The only working way to do that (that I have found) is to:

唯一可行的方法(我发现)是:

  1. prevent accept()from adding more clients

  2. have a list of the open sockets somewhere and to wait until they are all properly closed which means:

    • using shutdown()to tell the client that you will no longer work on that socket

    • call read()for a while to make sure that all the client has sent in the meantime has been pulled

    • then using close()to free each clientsocket.

  3. THEN, you can safely close()the listening socket.

  1. 防止accept()添加更多客户端

  2. 在某处有一个打开的套接字列表,并等待它们全部正确关闭,这意味着:

    • 使用shutdown()告诉客户端,您将在插座上不再工作

    • 调用read()一段时间以确保在此期间发送的所有客户端都已被拉取

    • 然后使用close()释放每个客户端套接字。

  3. 然后,您可以安全地close()监听套接字。

You can (and should) use a timeout to make sure that idle connections will not last forever.

您可以(并且应该)使用超时来确保空闲连接不会永远持续下去。

回答by msw

You are looking at a limitation of the TCP socket API. You can look at ECONNRESETas the socket version of EOFor, you can implement a higher level protocol over TCP which informs the client of an impending disconnection.

您正在查看 TCP 套接字 API 的限制。您可以将其ECONNRESET视为EOF或的套接字版本,您可以通过 TCP 实现更高级别的协议,该协议通知客户端即将断开连接。

However, if you attempt the latter alternative, be aware of the intractable Two Armies Problemwhich makes graceful shutdown impossible in the general case; this is part of the motivation for the TCP connection reset mechanism as it stands. Even if you could write graceful_close()in a way that worked most of the time, you'd probably still have to deal with ECONNRESETunless the server process can wait forever to receive a graceful_close_ackfrom the client.

但是,如果您尝试后一种选择,请注意棘手的两军问题,这使得在一般情况下无法正常关闭;这是 TCP 连接重置机制的部分动机。即使您可以graceful_close()以大部分时间都可以工作的方式编写,您可能仍然需要处理,ECONNRESET除非服务器进程可以永远等待graceful_close_ack从客户端接收 a 。