对于获取套接字系统调用(如recv
)错误,哪一个更好(在性能级别)?
- 使用普通的旧
errno
- 或者使用
SO_ERROR
作为getsockopt()
optname
我认为errno
(在我的系统中定义为__error()
)更快,因为它不是系统调用。我说得对吗?
SO_ERROR的优点是:获取后自动重置错误,并且我们确信错误只与我们的套接字有关。它更安全。
你认为哪一个更好?这两者的表现真的有什么不同吗?
引用Dan Bernstein的话:
情况:您设置了一个非阻塞套接字并执行connect(),返回-1/EINPROGRESS或-1/EWOULDBLOCK。您可以选择()套接字进行写入。一旦连接成功或失败,就会返回此消息。(例外:在一些旧版本的Ultrix中,select()在75秒超时之前不会注意到失败。)
问题:select()返回可写性后,你会怎么做?连接失败了吗?如果是,它是如何失败的?
如果连接失败,原因会隐藏在套接字中名为so.error的内容中。现代系统允许您使用getsockopt(,,so_error,,)查看so.error。。。
他接着讨论了getsockopt(,,SO_ERROR,,)
是一项现代发明,它不适用于旧系统,以及如何在这些系统上获得错误代码。但如果你为过去15年发布的Unix/Linux系统编程,你可能不需要担心。
connect
的Linux手册页描述了SO_ERROR
的相同用法。
因此,如果您在套接字上执行异步操作,可能需要使用SO_ERROR
。在任何其他情况下,只需使用errno
。
报价Unix网络编程:
如果进程调用read时
so_error
为非零,并且没有要返回的数据,读取返回–1,errno
设置为so_error的值(TCPv2第516页)。CCD_ 14的值随后被重置为0。如果有是排队等待套接字的数据,该数据通过读取返回错误条件的。如果进程调用时so_error
为非零write,返回–1,errno
设置为so_error
的值(第495页TCPv2的)并且CCD_ 18被重置为0。
因此,errno是更好的选择,除非您希望在数据完全提取之前立即得到错误。