Dean Chen
Dean Chen

Reputation: 3890

Why causes many CLOSE_WAIT in boost asio app?

I posted one question a few days ago, why my app based on boost::asio didn't accept new connection And I thought it was solved.

But it is not, today I can reproduce the error sometimes. After stopping/starting the 2000 client apps which connect to my TCP server. In some cases, many connections are shown as CLOSE_WAIT.

I close the connection manually using below code:

  void CloseSocket() {
    try {
      socket.shutdown(tcp::socket::shutdown_both);
      socket.close();
      BOOST_LOG_TRIVIAL(warning) << "close the connection";
    } catch (std::exception& e) {
      BOOST_LOG_TRIVIAL(warning) << "thread id: " << this_thread::get_id() << " " << e.what();
    }
  }

Also set address to be reused

  acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));

Some people said it's not recommended that closing the socket manually, let asio do it for you. But some people said you should call shutdown before close the socket. I use the latter way, but the problem still exists.

Upvotes: 4

Views: 2167

Answers (2)

Dean Chen
Dean Chen

Reputation: 3890

Finally, I resolved this problem because I add this command before lauching the server

ulimit -n 10240

Thanks everyone.

Upvotes: 0

Tanner Sansbury
Tanner Sansbury

Reputation: 51891

When a TCP connection is being closed:

  • The initiating side enters an active close. This will place the initiator's connection into a TIME_WAIT state, preventing the address from being reused as a means to guarantee late packets are not received as part of a new connection. The socket_base::reuse_address option allows for the address to be reused, even if the connection is in a TIME_WAIT state. This is often used to allow a server to restart and immediately begin listening to the same port.
  • The receiving side enters a passive close. The receiver's connection will remain in a CLOSE_WAIT state until the socket has been closed. When the socket is closed, it allowing the address to be released back and reused by the kernel.

As Igor R.'s succinctly suggest, the problem can be resolved by verifying that all paths allow for the socket to close. Based on your other question, given ClientType aggregates socket, and ClientType instances are managed by shared_ptr, it may be possible that ClientType instances are never being deleted, as the socket will close during its destruction.

Also, while socket_base::reuse_address will not affect CLOSE_WAIT, it may still be a good idea to use for the server's acceptor.

Upvotes: 3

Related Questions