RAII套接字:何时释放(关闭)

9
我想编写一个简单、小型的C++ RAII包装器,用于C套接字。
问题在于,从RAII的角度来看,何时认为套接字处于初始化状态,因此可以释放。
例如,对于TCP客户端套接字:如果socket调用成功,但connect调用失败,是否应该调用close
这只是一个例子,我对一般的答案感兴趣,类似于:
  • 每个由socket成功创建的套接字都必须关闭。
    或者
  • 必须有一个connectlistenaccept对应一个close
socket及其相关函数和close的手册并不太清楚(至少对我来说)。

如果您拥有一个有效/活动的套接字句柄,则它已被初始化。 - Captain Obvlious
@CaptainObvlious 什么时候套接字句柄被认为是有效/活动的? - bolov
socketaccept 返回一个非 INVALID_SOCKET 的值时,套接字句柄是有效的,直到你关闭该句柄。 - Captain Obvlious
@CaptainObvlious 谢谢,我认为这构成了一个答案。 - bolov
INVALID_SOCKET是一个WinSock常量,@CaptainObvlious。按照Unix传统,Linux使用文件描述符来索引从零开始的数组,因此任何小于零的值都是例如socket()的“错误”返回值。哦,而检查负值对于64位的WinSock会失败,因为那里套接字句柄类型是无符号整数,如果我没记错的话(我必须承认已经有一段时间了)。 - Ulrich Eckhardt
一种方法是创建一个非常简单的包装器,仅在包装器对象销毁时调用close。它还可以提供手动close()以显式关闭。这样做可以用很少的代码获得很多控制,并确保在异常情况下不会泄漏套接字描述符。 - Erik Alapää
1个回答

3
对于套接字的配对,需要使用socket()close(),以及connect()shutdown()。可以看到,与malloc()free()相比,并不那么容易。此外,由于并非每个套接字都用于connect(),有些还会使用bind()accept()。但是,如果您在没有调用shutdown()的情况下调用close(),这只是一种强制关闭方式,远程端会将其视为错误,但您确实正确释放了已分配的资源。

我建议进行两次封装,一次调用close(),另一次调用shutdown()。不过,如果无法成功调用shutdown(),也不必过于担心,因为它通常是无害的。


@bolov:正如Ulrich所说,你不需要过于担心调用shutdown,因为不这样做不会泄漏资源。所以我不会费心用RAII来包装它。在Unix上的规则非常简单:如果任何调用返回一个文件描述符>=0(opensocketacceptdup...),你必须close它以避免资源泄漏。 - Nemo

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