Asio结束套接字函数:取消,关闭,释放

7

如何正确关闭和清理套接字?

我在一个辅助线程中运行io_service,并且需要从主线程关闭连接:

void closeConnection()
{
    ioc.post([&socket]() {
        // Which ones do I have to call?
        // In what order?
        // What do they do?
        //socket.cancel();
        //socket.shutdown(asio::ip::tcp::socket::shutdown_both);
        //socket.close();
        //socket.release();
    });
    secondaryThread.join();
}

所有这些函数有什么区别?

我已经尝试过以下顺序...

socket.cancel();
socket.close();
socket.release();

看起来,连接关闭时没有出现错误,但是花费了太长时间(约5-10秒),因此我猜测我做错了什么。


我的代码中出现了一个愚蠢的错误。在处理read_async的函数中,即使错误代码为“false”,我仍然发布了另一个read_async。仍然认为有必要澄清所有这些函数的作用。 - tuket
1个回答

10
我猜你在谈论“优雅关闭”,即读取/写入任何未完成的数据,然后关闭套接字。
正确的步骤如下:
1. 调用`shutdown()`指示您将不再向套接字写入任何数据。
2. 继续从套接字(异步)读取,直到遇到错误或连接关闭。
3. 现在,在异步读取处理程序中`close()`套接字。
如果不这样做,你可能会在另一端仍在发送数据时关闭连接。这将导致不优雅的关闭。
`cancel()`和`release()`并不是正常流程中使用的调用:
- `cancel()`取消所有未完成的异步操作。 - `release()`释放底层本机套接字的所有权。

我的应用程序是一个聊天客户端,它正在等待异步读取,它不会在2中卡住吗?我可以使用“cancel()”取消异步读取吗?谢谢! - tuket
1
这就是 shutdown() 的作用 - 它会导致任何正在进行的异步读取以 "socket closed" 错误完成,此时您可以 close() socket。 - rustyx
好的,如果我理解正确的话,shutdown 做了 cancel 所做的一切,而且不允许未来的操作? - tuket
@tuket 不完全是这样。shutdown 函数启动套接字的关闭过程。如果对方向您发送数据,则未完成的读取可能会完成。cancel 函数取消未完成的异步操作,这会留下一堆问题。假设此时有数据正在传输给您,如果您取消未完成的异步操作,那么您将如何接收该数据呢? - David Schwartz
啊,我明白了。非常感谢! - tuket

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接