2010-01-27 89 views
11

我已閱讀了有關將套接字設置爲非阻塞模式的信息。如何將套接字重置爲阻塞模式(將其設置爲非阻塞模式後)?

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標誌?

謝謝。

+0

看看[這個答案](http://stackoverflow.com/a/18307077/514235)幫助。 – iammilind 2016-05-19 10:54:24

回答

14

您是否嘗試清除O_NONBLOCK標誌?

opts = opts & (~O_NONBLOCK) 
0

替代的方式來清除該標誌:

opts ^= O_NONBLOCK; 

這將切換非阻塞標誌,即禁用非阻塞如果當前已打開。

+5

如果已經清楚,切換會執行錯誤的操作。所以只需使用'opts&=〜O_NONBLOCK;'清除它。更簡單,更安全。 – 2015-04-16 02:20:24

5

這裏是一個更跨平臺的強大的解決方案:

bool set_blocking_mode(const 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; 
} 
+0

Linux也有一個'ioctl()'函數,它和WIN32'ioctlsocket()'一樣工作。 – 2015-12-06 01:46:42

+0

@AlexisWilke事實上,不過我的想法是,fcntl的API明確瞭如何獲取描述符的當前標誌,儘管我可以用它來進行第二次調用,但我試圖爲讀者節省潛在的第二次API查找。 – EntangledLoops 2015-12-07 17:09:30

+0

爲什麼'const int&'參數? – MikeMB 2016-09-15 12:55:06