为什么fcntl()标志值以八进制格式定义&这个函数如何用于阻塞/非阻塞套接字?

时间:2016-05-19 14:22:34

标签: c++ c sockets ssl fcntl

// "fcntl-linux.h" (with few lines skipped):
/* open/fcntl.  */
#define O_ACCMODE      0003
#define O_RDONLY         00
#define O_WRONLY         01
#define O_RDWR           02
#define O_APPEND      02000
#define O_NONBLOCK    04000
#define O_SYNC         04010000

每当在' 0'之后提及一个数字时,它就会变为八进制表示。选择较少传统的" Octal"格式超过更流行的十进制或十六进制?

this answer是阻止套接字无阻塞的正确方法吗? fcntl(socket, F_GETFL, 0)fcntl(socket, F_GETFL)之间有区别吗?

[注意:当我将套接字设置为非阻塞模式时,SSL连接不起作用。在阻止模式下,它工作正常。因此,描述模式设置的代码示例将是好的(如果它与链接代码不同)。]

2 个答案:

答案 0 :(得分:1)

没有真正的理由。如果它们是十进制的,它们也可以正常工作;电脑不在乎。

一般来说,"年龄较大"标志集通常以八进制定义,因为它们可以追溯到八进制比十六进制更受欢迎的时代。有人可能会猜测,开放标志可能是从其他操作系统中复制出来的,这些操作系统都是八进制的。

  • 4.4BSD确实有十六进制的fcntl / open标志(并且具有不同的值)
  • System V将它们以八进制形式存在,但又有不同的值。
  • Minix为Linux提供了重要的灵感和早期开发环境,它们具有八进制和相同的值。根据评论,它们显然是按照相关POSIX表的顺序顺序分配的(O_RDONLY / O_WRONLY / O_RDWR除外,这些表被分配了传统值)

答案 1 :(得分:0)

  

“为什么fcntl()标志值以八进制格式定义”

正如许多用户所建议的那样,纯粹是因为历史原因。显然,八进制格式比十六进制格式更强烈

  

this answer是阻止套接字非阻塞的正确方法吗?”

即可。答案是正确的,因为它的目的是设置标志,同时考虑各种情况。但是,错误检查会更有帮助,这是微不足道的。

  

fcntl(socket, F_GETFL, 0)fcntl(socket, F_GETFL)之间是否有区别?”

没有区别man page for fcntl(2)建议相同。

  

F_GETFL(void) - 获取文件访问模式和文件状态标志; arg被忽略。

与非阻塞套接字的SSL连接

这是一个有点棘手的部分,我遇到了问题。 SSL上的典型阻塞调用如下所示:

int result = ::SSL_connect(pSSL);  // <0: failed, 0: disconnected, 0<: pass

现在,天然的非阻塞替代方案,我们可以假设为:

::fcntl(socketfd, F_SETFL, m_fcntl);
::connect(socketfd, ...);
int result == ::SSL_connect(pSSL);
// put the FD_SET() etc.
result = select(...);
if(result == 0)  ... // SSL timed out
else if(result < 0) ... // SSL error 
else ... // success

然而,它并不像那样简单。 SSL是一个有点复杂的过程,消息来回交换。因此,我们必须在循环中运行::SSL_Connect()以捕获SSL_want_read, SSL_want_write。以简单的方式,代码可能如下所示:

::fcntl(socketfd, F_SETFL, m_fcntl);
::connect(socketfd, ...);
int result;  // looping for various handshakes & to/from messages
while((result = ::SSL_connect(pSSL)) < 0) {
  // put the FD_SET() etc.
  if(select(...) <= 0)
    break;
}
if(result == 0)  ... // SSL timed out
else if(result < 0) ... // SSL error 
else ... // success

我能够使用上面的(伪)代码修复我的SSL问题。

这个答案基于有用的评论&amp;我的发现。