2010-01-27 4 views
11

J'ai lu ceci au sujet du réglage d'un socket en mode non-bloquant.Comment réinitialiser une socket en mode blocage (après l'avoir réglée en mode non bloquant)?

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

Voici ce que je faisais:

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; 
} 

Comment puis-je régler la prise de retour en mode de blocage? Je ne vois pas de drapeau O_BLOCK?

Merci.

+0

Voir si [cette réponse] (http://stackoverflow.com/a/18307077/514235) aide. – iammilind

Répondre

14

Avez-vous essayé d'effacer le drapeau O_NONBLOCK?

opts = opts & (~O_NONBLOCK) 
0

Une manière alternative pour effacer l'indicateur:

opts ^= O_NONBLOCK; 

Cela bascule l'indicateur non-bloquant, à savoir désactiver la non-blocage si elles sont activées.

+5

Toggling ferait la mauvaise chose si c'est déjà clair. Il suffit donc de l'effacer en utilisant 'opts & = ~ O_NONBLOCK;'. Plus simple et plus sûr. –

5

Voici une solution capable plus multi-plateforme:

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 a aussi une fonction 'ioctl()' qui fonctionne comme WIN32 'ioctlsocket()'. –

+0

@AlexisWilke En effet, je pensais que l'API pour fcntl clarifiait comment obtenir les drapeaux actuels pour le descripteur, et bien que j'aurais pu l'utiliser pour le second appel, j'essayais d'économiser une seconde recherche d'API. – EntangledLoops

+0

pourquoi le paramètre 'const int &'? – MikeMB

Questions connexes