7
votes

RECV () renvoie 0

J'ai un problème très gênant que j'ai trouvé plusieurs fois sur d'autres forums, mais je ne trouve pas de solution appropriée. Le problème est RECV () renvoie 0 sur les derniers octets d'une connexion. Voici quelques informations de base.

  • Les applications (client / serveur) fonctionnent sur la même machine.
  • Les prises (client / serveur) sont non bloquantes
  • La taille de données transférée est de 53 octets.
  • (client / serveur) appelle l'arrêt et la fermeture de l'appel lorsque le dernier envoi () / RECV () a été exécuté.
  • J'ai aussi essayé avec SO_LINGER et 10 secondes, pas de succès

    J'appelle Envoyer () plusieurs fois (petits morceaux) et du côté du client 53 octets sont transférés. Le serveur appelle RECV () plusieurs fois (requêtes de 4 octets) et lisez 49 octets, puis retourne 0 (54 octets - 49 octets, donc 4 octets sont manquants).

    MSDN et certains forums écrivent pour des prises non bloquantes:

    • RECV () renvoie définitivement <0 sur erreur et errno / wsagetlasterror est défini
    • RECV () Retourne définitivement = 0 lorsque l'autre côté a fermé la connexion
    • RECV () retourne définitivement> 0 lorsque les données ont été lues

      MSDN dit également:

      Utilisation des fonctions de fermeture ou d'arrêt avec SD_SEND ou SD_BOTH Résultats dans un signal de libération étant envoyé sur le canal de contrôle. Dû à l'utilisation d'ATM de signal séparé et de canaux de données, il est possible que Un signal de libération pourrait atteindre l'extrémité distante avant le dernier de la Les données atteignent sa destination, entraînant une perte de ces données. Un Les solutions possibles programment un délai suffisant entre le dernier données envoyées et la fonction de fermeture ou d'arrêt appelle à un guichet automatique Prise.

      Ceci est considéré dans l'exemple de RECV () et d'envoi (): http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121 (v = vs.85) .aspx

      Mais toujours pas de succès, je reçois toujours des interruptions dans 10% de toutes les connexions après la réception des 49 octets, 90% des connexions réussissent. Des idées? Thx.


2 commentaires

Je soupçonne que vous faites partie de plusieurs erreurs de programmation de socket classiques. J'ai quelques idées, mais je préférerais voir votre code avant d'écrire quelque chose.


SO_LINGER avec un délai d'attente positif en mode non bloquant n'a pas de sens. Il ne bloquera ni le délai d'expiration.


3 Réponses :


16
votes

RECV () retourne 0 uniquement lorsque vous demandez un tampon de 0 octet ou que l'autre pair a gracieusement déconnecté. Si vous ne recevez pas toutes les données que vous attendez, vous ne lisez pas correctement les données pour commencer. Veuillez mettre à jour votre question avec votre code actuel.


0 commentaires

-1
votes

Je suppose que vous n'envoyez pas vraiment toutes les données que vous pensez être envoyées. Découvrez:

la page Ultimate SO_LINGER


2 commentaires

Qu'est-ce que SO_LINGER a à voir avec ne pas envoyer toutes les données que vous pensez que vous envoyez?


Parce que c'est tout le problème SO_LINGER. Vous écrivez toutes vos données (vous pensez) et fermez votre prise. Ce que vous avez réellement fait a été mis les données sur le tampon d'envoi du système d'exploitation ... puis fermée la prise. L'autre côté voit des données partielles puis une étroite.



-1
votes
  • RECV () Retourne définitivement = 0 lorsque l'autre côté a fermé la connexion li> ul>

    Ceci n'est pas complètement vrai, dans le code suivant à l'aide de Winsock2 TCP sans blocage, lorsque aucune donnée n'est disponible, sélectionnez Retours 1 et RECV renvoie 0, de même que WsageTlasterRor (). P>

    ::shutdown(socket, SD_BOTH);
    ::closesocket(socket);
    

1 commentaires

Si RECV () renvoie zéro, la peer a fermé la connexion. Le mode non bloqué n'a rien à voir avec cela.