如何拆除boost::asio::ip::udp::socket?

11

我已经阅读了boost asio参考资料,完成了教程并查看了一些示例。但我仍然无法确定套接字应该如何被关闭:

  1. 我应该调用close()还是由套接字的析构函数来完成?
  2. 我应该在什么时候调用shutdown()?
  3. shutdown()的效果是什么?我知道它“禁用发送或接收”,但这是如何实现的?如果在禁用后使用套接字进行发送或接收,会有什么预期结果?
  4. close()可能产生哪些错误?
2个回答

11

由于这是一个多问题,我会尽力回答每个部分以满足您的要求:

1)根据我的经验,ASIO套接字的析构函数会处理关闭套接字。 但是,我只处理过TCP套接字。 最好的方法是查看析构函数的代码,看它是否执行类似于关闭操作。 我知道Boost代码可能有点棘手,所以最简单的方法可能是创建一个打开UDP套接字然后销毁它的小示例程序。 这样,您可以在调试器中逐步跟踪逻辑。

由于Boost的设计者已考虑到TCP套接字,我很难想象他们不会对UDP套接字做同样的处理。

2)仅在您认为需要防止任何代码对套接字执行未来的recv和/或send时才调用shutdown()。通常不需要,但我曾在TCP套接字上使用它,以强制套接字在关闭时发送RST(而不是默认的“优雅”关闭,在那里挂起的发送处理)。

3)您可以将套接字视为一种双通道通信形式:一个用于读取,另一个用于发送。 您可以独立关闭其中任何一个,当关闭其中一个通道时,您仍然可以继续使用另一个通道(即,在关闭发送或接收后仍然可以接收)。 关闭套接字等同于在recv和send上调用shutdown。

关闭recv仅会阻止您的代码读取更多数据。 如果您尝试这样做,将会收到套接字错误。 同样,如果连接的另一侧尝试向您发送数据,则会收到错误(对不起,我又切换到TCP世界,但我相信会回复一个RST给发送方)。

关闭发送同样会阻止您的代码发送任何更多的数据。如果我没记错的话,这看起来与关闭套接字时发生的情况完全相同(发送一个零长度的数据包来向另一端信号特定通道已被关闭)。任何未来的发送尝试将返回错误。

4) 您需要检查文档才能确定。 MSDN会给你一个相当好的指示,但我不知道我是否认为它是权威的。


谢谢,我已经理解了其中一些内容,但仍然不确定close()是否真的在套接字的析构函数中被调用。我真正没有理解的是boost asio和传统网络编程之间的紧密联系。你对shutdown()的解释以及建议查看msdn套接字错误代码都表明了这一点。+1 - Torleif
就我个人而言,对于UDP套接字,在Windows上调用.shutdown(BOTH)可以正常工作,但在Linux上会出现问题,因为该套接字未连接。 - Alastair Maw

1

从Boost网站给出的示例来看,似乎应该简单地使用close()。例如,看看这个:

void connection::stop()
{
  socket_.close();
}

取自此地址:HTTP服务器


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