代码
asio\asio\detail\impl
int close(socket_type s, state_type& state,
bool destruction, asio::error_code& ec)
{
int result = 0;
if (s != invalid_socket)
{
//要在析构函数中避免阻塞,可以设置套接字的 SO_LINGER 选项,以便在套接字关闭时不等待所有数据传输完毕。
//这个设置允许套接字在后台进行关闭操作。如果用户不希望这种行为,他们需要显式地关闭套接字
if (destruction && (state & user_set_linger))
{
::linger opt;
opt.l_onoff = 0;
opt.l_linger = 0;
asio::error_code ignored_ec;
socket_ops::setsockopt(s, state, SOL_SOCKET,
SO_LINGER, &opt, sizeof(opt), ignored_ec);
}
clear_last_error();
#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)
result = error_wrapper(::closesocket(s), ec);
#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
result = error_wrapper(::close(s), ec);
#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
if (result != 0
&& (ec == asio::error::would_block
|| ec == asio::error::try_again))
{
//在 UNIX 网络编程中,close() 函数在某些情况下可能会返回 EWOULDBLOCK 错误。这种情况下,套接字的状态可能不明确。
//在 Windows 操作系统中,如果出现这种情况,套接字会保持打开状态。因此,可以将描述符设置回阻塞模式,并再次尝试关闭它
#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)
ioctl_arg_type arg = 0;
::ioctlsocket(s, FIONBIO, &arg);
#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
# if defined(__SYMBIAN32__)
int flags = ::fcntl(s, F_GETFL, 0);
if (flags >= 0)
::fcntl(s, F_SETFL, flags & ~O_NONBLOCK);
# else // defined(__SYMBIAN32__)
ioctl_arg_type arg = 0;
::ioctl(s, FIONBIO, &arg);
# endif // defined(__SYMBIAN32__)
#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
state &= ~non_blocking;
clear_last_error();
#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)
result = error_wrapper(::closesocket(s), ec);
#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
result = error_wrapper(::close(s), ec);
#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
}
}
if (result == 0)
ec = asio::error_code();
return result;
}
分析
#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)
result = error_wrapper(::closesocket(s), ec);
#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
result = error_wrapper(::close(s), ec);
#endif // defined(ASIO_WINDOWS) || defined(CYGWIN)
从这里可以看到我们非常熟悉的关闭套接字的函数调用