IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Réseau C Discussion :

ne pas rester bloqué sur un connect


Sujet :

Réseau C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2004
    Messages : 58
    Par défaut ne pas rester bloqué sur un connect
    Bonjour à tous,

    Voici mon problème:
    J'ai une application redondante sous XP avec 3 threads, 2 sont utilisé pour savoir si l'ordinateur partenaire est actif, le troisième est le thread principal de l'application.

    Le thread principal doit de temps en temps copier ses fichiers à jours sur le partenaire (via un partage netbios), si celui-ci est dispo.

    Pour celà un des thread va tenter de temps en temps de voir si le port netbios 139 est ouvert sur le partenaire en faisant un connect sur ce port.

    Le problème est que si le partenaire est débranché du réseau, le connect va bloquer mon thread le temps d'avoir un timeout sur la socket (ça prends plus de 30 secondes) et le pire, c'est que le thread qui est en attente d'entrées/sorties ne rends pas la main. mon application reste donc bloquée pendant 30 secondes, alors que le temps de cycle ne doit pas dépasser 10 secondes (plus ou moins temps réel)

    J'ai tenté de jouer avec SO_SNDTIMEO mais rien n'y fait, voici mon code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
     
    int tcp_init_client(char *server_name, unsigned short port, SOCKET *cli_sock, int required_timetout)
    {
      int                 errnr = -999;
      unsigned int        addr;
      int                 socket_type = TCP_SOCKET_TYPE, ret;
      struct sockaddr_in  server;
      struct hostent      *hp;
      int                 timeout;
      time_t t;
      char strtime[255];
     
      if (port == 0)
      {
        return -1;
      }
     
        hp = gethostbyname(server_name);
     
     
      if (hp == NULL)
      {
     
        errnr = WSAGetLastError();
     
        trc_msg(ERR_TCP, INDENT_0, ERR, 0, "TCP Client: Cannot resolve address [%s]: Error %d", server_name, errnr);    
        return -1;
      }
     
      /* Copy the resolved information into the sockaddr_in structure */
      memset(&server, 0, sizeof(server));
      memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);
      server.sin_family = hp->h_addrtype;
      server.sin_port = htons(port);
     
      *cli_sock = socket(AF_INET, socket_type, 0);  /* Open a socket */
      if (*cli_sock == INVALID_SOCKET)
      {
        errnr = WSAGetLastError();
        trc_msg(ERR_TCP, INDENT_0, ERR, 0, "TCP Client: Error Opening socket: Error %d", errnr);
        return -1;
      }
     
      timeout = required_timetout;
      /*We set a send timeout in order to detect that a client is down*/
     
      if (ret = setsockopt(*cli_sock, SOL_SOCKET, SO_SNDTIMEO, (char*) &timeout, sizeof(timeout)))
      {
        errnr = WSAGetLastError();
     
        trc_msg(ERR_TCP, INDENT_0, ERR, 0, "Setsockopt SO_RCVTIMEO failed with error:%d", errnr);
      }
     
     
      trc_msg(ERR_TCP, INDENT_0, INFO, 0, "TCP Client connecting to: %s (%d)", hp->h_name);
     
      t = (time(NULL) + 0);
      strftime(strtime, 255, "%Y%m%d %X\t", my_localtime(&t));
      printf("\n time before:%s", strtime);
      if (connect(*cli_sock, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR)
      {
        errnr = WSAGetLastError();
     
        t = (time(NULL) + 0);
        strftime(strtime, 255, "%Y%m%d %X\t", my_localtime(&t));
        printf("\n time after:%s", strtime);
        if (!quietmode)
          trc_msg(ERR_TCP, INDENT_0, ERR, 0, "TCP Client connect %s (%d) failed: %d", hp->h_name, port, errnr);
        return -1;
      }   
      return 0;
    }
    voilà, je n'ai pas d'erreur lors du setsockopt()
    par contre je n'arrive pas à lire SO_RCVTIMEO avec getsockopt(), chaque fois il me donne l'erreur WSAEFAULT 10014

    D'après mes recherches, fixer SO_SNDTIMEO ou SO_RCVTIMEO ner fonctionne pas des masses.

    Je cherche donc désespérément une solution.

    J'accepetrais volontier d'utiliser un select, mais comment faire sur une socket client?

    merci de toutes vos propositions

  2. #2
    Membre Expert Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Par défaut
    La réponse à ta question se trouve dans la documentation de ton système:
    http://msdn.microsoft.com/en-us/libr...25(VS.85).aspx
    je cite
    With a nonblocking socket, the connection attempt cannot be completed immediately. In this case, connect will return SOCKET_ERROR, and WSAGetLastError will return WSAEWOULDBLOCK. In this case, there are three possible scenarios:
    1. Use the select function to determine the completion of the connection request by checking to see if the socket is writeable.

    1. If the application is using WSAAsyncSelect to indicate interest in connection events, then the application will receive an FD_CONNECT notification indicating that the connect operation is complete (successfully or not).

    1. If the application is using WSAEventSelect to indicate interest in connection events, then the associated event object will be signaled indicating that the connect operation is complete (successfully or not).

  3. #3
    Membre Expert Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Par défaut
    Si tu te demandes comment on rend une socket non bloquante sous Windows, je te renvoie encore une fois à la documentation:
    http://msdn.microsoft.com/en-us/libr...73(VS.85).aspx
    Cordialement.

  4. #4
    Membre confirmé
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2004
    Messages : 58
    Par défaut
    Merci Nicolas de tes réponses vives et anticipantes.

    Ce que dit la doc, c'est donc que je dopis utiliser des socket non-bloquantes. C'est un epu moche mais bon, je veux bien, même si ça va poser des problèmes de portabilité mais ça, je peux encore vivre avec.
    En fait, j'avais déjà tenté ça mais je reste bloqué à un certain point.
    Mon but est de créer une socket, de la définir non bloquante puis de la connecter. ensuite je fais un selcet qui devrait me permetre de voir si j'ai une erreur du type WOULD_BLOCK avec un timeout de 1 sec, ça devrait me permettre de m'en sortir.

    Voici le code que j'ai utilisé:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
     
    int tcp_is_server_available(char *server_name, unsigned short port, SOCKET *cli_sock, int timeout_wait)
    {
      int                 nb, errnr = -999;
      unsigned int    addr;
      int                 socket_type = TCP_SOCKET_TYPE, ret;
      struct sockaddr_in  server;
      struct hostent      *hp;
      time_t t;
      char strtime[255];
      long            status = 0;
      struct timeval  timeout;
      u_long iMode = 1; /*Set the socket to non-blocking mode (more than 0)*/
      fd_set          writefds;
     
     
     
       /* server address is a name */
        hp = gethostbyname(server_name);
     
      if (hp == NULL)
      {
        errnr = WSAGetLastError();
     
        printf( "TCP Client: Cannot resolve address [%s]: Error %d", server_name, errnr);    
        return -1;
      }
     
      /* Copy the resolved information into the sockaddr_in structure */
     
      memset(&server, 0, sizeof(server));
      memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);
      server.sin_family = hp->h_addrtype;
      server.sin_port = htons(port); 
     
      *cli_sock = socket(AF_INET, socket_type, 0);  /* Open a socket */
     
     
      if (*cli_sock == INVALID_SOCKET)
      {
        errnr = WSAGetLastError();
        printf( "TCP Client: Error Opening socket: Error %d", errnr);
        return -1;
      }
      ioctlsocket(cli_sock, FIONBIO, &iMode); /* set non-blocking*/
     
      if (connect(*cli_sock, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR  )
      {
        errnr = WSAGetLastError();
        printf("TCP Client connect %s (%d) failed: %d", hp->h_name, port, errnr);
        return -1;
      }
     
      /* prepare read descriptor */
      FD_ZERO(&writefds);
      FD_SET(cli_sock, &writefds);
     
      /* Set timeout at 0 for select () ==> immediate return from select */
      timeout.tv_sec = timeout_wait / 1000;
      timeout.tv_usec = (timeout_wait - timeout.tv_sec * 1000) * 1000;
     
     
      /* Check if socket ready to be written*/
      nb = select(FD_SETSIZE, NULL, &(writefds), NULL, &(timeout));
     
      /* if error */
      if (nb < 0)
      {
        status = -1;
        errnr = WSAGetLastError();
        printf("TCP select() returned %ld, error %ld", nb, errnr);
        return -1;
      }
      else
      {
        status = 0;
     
        /* check if at least one descriptor is ready AND it's the correct descriptor */
     
        if (FD_ISSET(cli_sock, &writefds))
        {
          /* we can write */
          return 1;
        }
        else
        {
          /* we can not write */
          return 0;
        }
      }
    }
    cependant, la fonction select me retourne toujours -1 avec l'erreur :WSAENOTSOCK 10038

    Est ce qu'un paramètre de moon fdset n'est pas valide?
    au départ je pensais qu'on nepouvait simplement pas utiliser select sur une connection client.

    NB, avec wireshark, je vois que le 3handshake se passe bien, la connection est ouverte entre mon pc et le pc partenaire...

    N'hésitez pas à me traiter de tous les noms si vous voyez une grosse erreur..

    Merci encore.

  5. #5
    Membre Expert Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Par défaut
    Citation Envoyé par gigiskhan Voir le message
    cependant, la fonction select me retourne toujours -1 avec l'erreur :WSAENOTSOCK 10038

    Est ce qu'un paramètre de moon fdset n'est pas valide?

    N'hésitez pas à me traiter de tous les noms si vous voyez une grosse erreur..
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FD_SET(*cli_sock, &writefds);

  6. #6
    Membre confirmé
    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2004
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : Réunion

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2004
    Messages : 58
    Par défaut
    Merci de ne pas m'avoir insulté,

    Je n'arrive toujours pas à faire respecter de timeout que je fixe, mais je vais travailler le truc de mon côté, je reviens clore le sujet dès que j'ai trouvé.

    Merci encore Nicolas

  7. #7
    Membre Expert Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Par défaut
    Citation Envoyé par gigiskhan Voir le message
    Merci de ne pas m'avoir insulté,
    ça n'arrivera pas sur ce forum.

    Citation Envoyé par gigiskhan Voir le message
    Je n'arrive toujours pas à faire respecter de timeout que je fixe
    Précise ton problème s'il te plaît.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 22/08/2014, 16h58
  2. Réponses: 2
    Dernier message: 12/03/2008, 16h51
  3. Réponses: 9
    Dernier message: 19/12/2007, 15h42
  4. Réponses: 9
    Dernier message: 16/11/2007, 11h33
  5. rester bloqué sur une zone de texte
    Par Pitou5464 dans le forum Access
    Réponses: 3
    Dernier message: 18/08/2006, 18h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo