9
votes

Socket () renvoie 0 en application de serveur client C

Je travaille sur une application contenant plusieurs sockets de serveur qui fonctionnent chacun dans un fil unique.
Un utilitaire externe (script) est appelé par l'un des threads. Ce script appelle un utilitaire (client) qui envoie un message à l'une des sockets de serveur.

Initialement, j'utilisais System () code> pour exécuter ce script externe, mais nous ne pouvions pas utiliser ça Parce que nous devions nous assurer que les prises de serveur étaient fermées dans l'enfant qui a été forcée pour exécuter le script externe.
J'appelle maintenant fourchette () code> et Execvp () code> moi-même. I fourchette () code> puis dans l'enfant, je ferme toutes les prises de serveur, puis appelez exécuvp () code> pour exécuter le script. P>

maintenant, tout de cela fonctionne bien. Le problème est que, parfois, le script rapporte des erreurs sur l'application Server. Le script envoie ces erreurs en appelant une autre application (client) qui ouvre une prise TCP et envoie les données appropriées. Mon problème est que l'application client reçoit une valeur de 0 code> retourné par la prise () code> appel système. P>

Remarque: cela ne se produit que lorsque le script / L'application client est appelée à l'aide de ma fonction Forkexec (). Si l'application Script / client est appelée manuellement, la prise () code> L'appel effectue de manière appropriée et les choses fonctionnent bien. P>

basé sur ces informations que je soupçonne que c'est quelque chose dans ma fourchette () Execvp ( ) Code ci-dessous ... des idées? P>

if (socketFD < 0)
{
    fprintf(stderr, "%s-%d: Failed to create socket: %s", 
                                __func__, __LINE__, strerror(errno));
    return (-1);
}

memset(&address, 0, sizeof(struct sockaddr));
address.sin_family = AF_INET;
memcpy(&(address.sin_addr.s_addr), hostAddr->h_addr, hostAddr->h_length);
address.sin_port = htons(POLLING_SERVER_PORT);

status = connect(socketFD, (struct sockaddr *)&address, sizeof(address));
if (status < 0)
{
    if (errno != ECONNREFUSED)
    {
        fprintf(stderr, "%s-%d: Failed to connect to server socket: %s",
                   __func__, __LINE__, strerror(errno));
    }
    else
    {
        fprintf(stderr, "%s-%d: Server not yet available...%s",
                   __func__, __LINE__, strerror(errno));
        close(socketFD);
        socketFD = 0;
    }
}

return socketFD;
}


2 commentaires

Pourriez-vous publier le code qui appelle la prise () s'il vous plaît?


Aucune idée encore ce qui arrive à votre prise. Peut-être que c'est de l'aide pour vous si je souligne que vous pouvez déclarer vos arguments beaucoup plus simples: const Char * progargs [] = {"/ path_to_script", arg, null}; - Pas besoin d'allouer et de copier, tout ce dont vous avez besoin est un tableau avec les bons pointres au moment où vous appelez Execvp.


4 Réponses :


1
votes

N'oubliez pas d'appel à

waitpid()


1 commentaires

Ouais, j'ai déjà un gestionnaire de sigchld enregistré qui effectue des zombies alterpid () pour nettoyer les zombies. Merci quand même :)



15
votes

socket () renvoie -1 sur erreur.

Retour de 0 signifie socket () a réussi et vous a donné un descripteur de fichier 0. Je soupçonne que l'un des descripteurs de fichiers que vous fermez a un descripteur de fichier 0 et une fois qu'il est fermé l'appel suivant à une fonction affectée un descripteur de fichier retourne fd 0 car il est disponible.


6 commentaires

Oui, c'est ce que j'ai soupçonné. Mais non, je n'ai rien fait de tel.


Il retourne 0 (comme votre question indique-t-il) ou renvoie-t-il une valeur négative (comme votre exemple de vérification de votre code)? Réitérer, un retour de 0 est complètement légal si FD 0 est disponible.


Ça retourne zéro. Je comprends que 0 est une FD valide. Le problème ici doit avoir quelque chose à voir avec ma fonction Forkexec () car si je modifie pour utiliser le système System () Socket Retours> 0. Malheureusement, je ne peux pas utiliser l'appel système ().


Le système utilise la coquille pour exécuter le nouveau programme. Je suppose que la coquille ouvre la FD 0 (qui est ensuite héritée par votre sous-programme), il n'est donc plus disponible lorsque la prise () est appelée.


Le système () appelle les exécutions / bin / sh -c, mais ni l'appel système () ni / bin / sh ne fermera les descripteurs de fichiers comme vous le faire à ForKexec ()


Correct! L'un des FD que je ferme était fixé à zéro, il n'a pas encore été initialisé. Merci!



8
votes

Une prise avec valeur 0 est bien, cela signifie que STDIN a été fermé qui rendra FD 0 disponible pour la réutilisation, par exemple par une prise.

chances sont l'un des fichiers FileDescripteurs que vous fermez dans le chemin Forkexec () enfant (xmlsocket / serverfd), etc.) était FD 0. Ça va commencer l'enfant avec FD 0 fermé, qui n'arrivera pas lorsque vous exécutez l'application à partir d'une ligne de commande, car Fd 0 sera déjà ouvert comme STDIN de la coque. P>

Si vous le souhaitez. Votre prise ne doit pas être 0,1 ou 2 (stdin / out / outr) appelez les éléments suivants dans votre fonction ForKexec () après tous les appels de fermeture () P>

void reserve_tty()
{
  int fd;

  for(fd=0; fd < 3; fd++)
    int nfd;
    nfd = open("/dev/null", O_RDWR);

    if(nfd<0) /* We're screwed. */
    continue;

    if(nfd==fd)
    continue;

    dup2(nfd, fd);
    if(nfd > 2)
     close(nfd);

}


2 commentaires

Mais pourquoi stdin est-il fermé? Pourquoi voudrait-il faire cela intentionnellement?


Il est courant (bien que souvent ils sont redirigés vers / dev / null comme indiqué dans le code ci-dessus maintenant) et une bonne pratique pour fermer toutes les FD ne sont pas nécessaires dans un processus de fond / démon, que je suppose que le processus des parents est.



0
votes

Comme cela est mentionné dans un autre commentaire, vous ne devez vraiment pas fermer 0,1 ou 2 (STDIN / OUT / OUT / ERR), vous pouvez vérifier que vous ne fermez pas de les fermer et que cela ne sera donc pas attribué nouveau FD`s lorsque vous demandez un nouveau socket


0 commentaires