【问题标题】:How to reset a socket back to blocking mode (after I set it to nonblocking mode)?如何将套接字重置为阻塞模式(在我将其设置为非阻塞模式之后)?
【发布时间】:2011-01-10 02:59:38
【问题描述】:

我已经阅读了有关将套接字设置为非阻塞模式的内容。

http://www.gnu.org/software/libc/manual/html_mono/libc.html#File-Status-Flags

这是我所做的:

static void setnonblocking(int sock)
{
    int opts;

    opts = fcntl(sock,F_GETFL);
    if (opts < 0) {
        perror("fcntl(F_GETFL)");
        exit(EXIT_FAILURE);
    }
    opts = (opts | O_NONBLOCK);
    if (fcntl(sock,F_SETFL,opts) < 0) {
        perror("fcntl(F_SETFL)");
        exit(EXIT_FAILURE);
    }
    return;
}

如何将套接字设置回阻塞模式?我没有看到 O_BLOCK 标志?

谢谢。

【问题讨论】:

标签: c sockets networking blocking nonblocking


【解决方案1】:

您是否尝试清除 O_NONBLOCK 标志?

opts = opts & (~O_NONBLOCK)

【讨论】:

    【解决方案2】:

    这是一个更具跨平台能力的解决方案:

    bool set_blocking_mode(int socket, bool is_blocking)
    {
        bool ret = true;
    
    #ifdef WIN32
        /// @note windows sockets are created in blocking mode by default
        // currently on windows, there is no easy way to obtain the socket's current blocking mode since WSAIsBlocking was deprecated
        u_long non_blocking = is_blocking ? 0 : 1;
        ret = NO_ERROR == ioctlsocket(socket, FIONBIO, &non_blocking);
    #else
        const int flags = fcntl(socket, F_GETFL, 0);
        if ((flags & O_NONBLOCK) && !is_blocking) { info("set_blocking_mode(): socket was already in non-blocking mode"); return ret; }
        if (!(flags & O_NONBLOCK) && is_blocking) { info("set_blocking_mode(): socket was already in blocking mode"); return ret; }
        ret = 0 == fcntl(socket, F_SETFL, is_blocking ? flags ^ O_NONBLOCK : flags | O_NONBLOCK));
    #endif
    
        return ret;
    }
    

    【讨论】:

    • Linux 还有一个ioctl() 函数,其工作方式类似于WIN32 ioctlsocket()
    • @AlexisWilke 确实,但是我的想法是 fcntl 的 API 清楚地说明了如何获取描述符的当前标志,尽管我可以将它用于第二次调用,但我试图保存读者可能会进行第二次 API 查找。
    • 为什么是const int &amp; 参数?
    • @MikeMB 只是我从代码库中提取此示例的一个工件。没必要。
    【解决方案3】:

    清除标志的另一种方法:

    opts ^= O_NONBLOCK;
    

    这将切换非阻塞标志,即如果当前启用,则禁用非阻塞。

    【讨论】:

    • 如果已经很清楚,切换会做错事。所以只需使用opts &amp;= ~O_NONBLOCK; 清除它。更简单、更安全。
    猜你喜欢
    • 1970-01-01
    • 2010-11-24
    • 1970-01-01
    • 2012-01-14
    • 2010-10-26
    • 2011-12-19
    • 2015-11-27
    • 2012-02-15
    • 2012-11-26
    相关资源
    最近更新 更多