Question

Je travaillais avec un serveur TCP et quelque chose ultra bizarre se présentaient.

Lorsque je me connecte avec un client, everythings va bien.
Lorsque deux ou plusieurs client se connecte, le trafic est toujours très bien.
Mais lorsque l'un des clients sectionneurs, les confitures de serveur juste après l'appel reaper. Il se trouve juste là à attendre.

J'ai découvert quand je suis déconnecté 1 client sur 2 et on a essayé de reprendre contact. Le client rebranchement n'affiche aucun message d'erreur du tout, il fonctionne bien. Les paquets peuvent être envoyés au serveur, mais il empile à l'intérieur du serveur.

Le serveur sur l'autre, il se bloque à la main, en attendant un client spécifique à déconnecter. Si cette client se déconnecte, le serveur reprendra la fonction, l'exécution de toutes les demandes qui ont été entassées à l'intérieur.

Voici le code barebone j'ai utilisé pour la structure du serveur.
Ce code démontre aussi le problème indiqué ci-dessus.
Quelqu'un peut-il s'il vous plaît, s'il vous plaît, s'il vous plaît indiquer où l'erreur a été commise?

void    reaper(int sig)
{
int status;

while (waitpid(-1, &status, WNOHANG) >= 0)
    /* empty */;
}


int     errexit(const char *format, ...)
{
    va_list args;

    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);
    exit(1);
}




int     errno;

unsigned short  portbase = 0;   /* port base, for non-root servers      */

int     passivesock(const char *service, const char *transport, int qlen)

{
    struct servent  *pse;   /* pointer to service information entry */
    struct protoent *ppe;   /* pointer to protocol information entry*/
    struct sockaddr_in sin; /* an Internet endpoint address         */
    int     s, type;        /* socket descriptor and socket type    */

    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = INADDR_ANY;

/* Map service name to port number */
    if ( pse = getservbyname(service, transport) )
            sin.sin_port = htons(ntohs((unsigned short)pse->s_port)
                    + portbase);
    else if ((sin.sin_port=htons((unsigned short)atoi(service))) == 0)
            errexit("can't get \"%s\" service entry\n", service);

/* Map protocol name to protocol number */
    if ( (ppe = getprotobyname(transport)) == 0)
            errexit("can't get \"%s\" protocol entry\n", transport);

/* Use protocol to choose a socket type */
    if (strcmp(transport, "udp") == 0)
            type = SOCK_DGRAM;
    else
            type = SOCK_STREAM;

/* Allocate a socket */
    s = socket(PF_INET, type, ppe->p_proto);
    if (s < 0)
            errexit("can't create socket: %s\n", strerror(s));

/* Bind the socket */
    if (errno=bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
            errexit("can't bind to %s port: %s\n", service,
                    strerror(errno));
    if (type == SOCK_STREAM && listen(s, qlen) < 0)
            errexit("can't listen on %s port: %s\n", service,
                    strerror(type));
    return s;
}

int     passiveTCP(const char *service, int qlen)
{
    return passivesock(service, "tcp", qlen);
}




#define QLEN              32    /* maximum connection queue length      */
#define BUFSIZE         4096


int     TCPechod(int fd);

int main(int argc, char *argv[])
{
    char    *service;      /* service name or port number  */
    struct  sockaddr_in fsin;       /* the address of a client      */
    unsigned int    alen;           /* length of client's address   */
    int     msock;                  /* master server socket         */
    int     ssock;                  /* slave server socket          */

    if (argc !=2)
            errexit("usage: %s port\n", argv[0]);

    service = argv[1];

    msock = passiveTCP(service, QLEN);

    (void) signal(SIGCHLD, reaper);

    while (1) {
            alen = sizeof(fsin);
            ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
            if (ssock < 0) {
                    if (errno == EINTR)
                            continue;
                    errexit("accept: %s\n", strerror(ssock));
            }
            printf("Accept connection %d from %s:%d\n", ssock, inet_ntoa(fsin.sin_addr), (int)ntohs(fsin.sin_port));
            switch (fork()){
            case 0:
                (void) close(msock);
                TCPechod(ssock);
                close(ssock);
                exit(0);
            default:
                close(ssock);
                break;
            case -1:
                errexit("fork: %s\n", strerror(errno));
            }              
    }
}


int     TCPechod(int fd)
{
    char    buf[BUFSIZE];
    int     cc;

    while (cc = read(fd, buf, sizeof(buf))) {
            if (cc < 0)
                    errexit("echo read: %s\n", strerror(cc));
            if (errno=write(fd, buf, cc) < 0)
                    errexit("echo write: %s\n", strerror(errno));
    }
    return 0;
}

Les heads-up serait grandement appréciée.
Je vous remercie à l'avance.

Était-ce utile?

La solution

Le problème est de savoir comment vous appelez waitpid, parce que vous laissez seulement le temps quand une erreur est survenue (retour waitpid <0 si une erreur est survenue). Lorsque vous appelez Waitpid avec le drapeau WNOHANG, il retourne 0 s'il n'y a pas de processus enfant mis fin (vraiment de changer d'état: arrêté, reprise ou terminée). Essayez cette correction:

void reaper(int sig)
{
  int status;
  pid_t pid;
  while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
    printf("Proces PID: %d Hash Finished With Status: %d", pid, status);
  if (0 == pid) printf("No More Process Waiting");
  if (pid < 0) printf("An Error Ocurred");
}

Si vous souhaitez utiliser la fonction attendre reaper doit être quelque chose comme:

void reaper(int sig)
{
  int status;
  pid_t pid;
  pid = wait(&status); // Wait suspend the execution of the current process.
  if (pid > 0) printf("Proces PID: %d Hash Finished With Status: %d", pid, status);
  if (pid < 0) printf("An Error Ocurred");
}

Pour plus d'informations au sujet d'attente (2) aller à: http://linux.die.net / homme / 2 / attente

Autres conseils

je suis tombé sur ce problème aussi bien.

La fonction « reaper » avec le test >=0 est en exemples dans tous les sens, mais cela peut finir par être une boucle sans fin car même une fois qu'il nettoie l'enfant il va garder en boucle pas jusqu'à ce qu'il n'y a pas de plus, mais jusqu'à ce qu'il obtienne une erreur de quelque sorte.

Il existe des versions Perl de ce code là-bas qui est habituellement « fixe » à l'aide >0 au lieu de >=0, mais vous voudrez peut-être utiliser la logique comme indiqué ici où vous tester explicitement les cas d'intérêt.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top