Newsgroup: it.comp.lang.c
Titolo: Help individuazione bug in codice (molto semplice)

Salve gente!
Per motivi che non sto a spiegare (molto lunghi) ho la necessitï¿œ di un 
"echo server tcp/ip" in ambiente linux al quale mi connetto con un'app 
windows (scritta da me).
Ho trovato in rete il seguente codice che funge perfettamente ad 
eccezione del momento della disconnessione del client.
In pratica al momento della disconnessione, il server inizia a ripete 
all'infinito questo "stralcio" del programma:
 
 
printf("-------------------------------------------------------\n");
             mesg[n] = 0;
             printf("Received the following:\n");
             printf("%s",mesg);
 
printf("-------------------------------------------------------\n");
 
 
non ho modo di effettuare il debug in quanto sono in un'ambiente 
embedded e non sono cosï¿œ ferrato in linguaggio C (reminescenze di 20 
anni fï¿œ...)
 
Vorrei capire perchï¿œ diavolo non torna in "listen" ma continua a stare 
in loop nel ciclo for(;;)...credo nel secondo ciclo.
 
Ho provato anche con un semplice telnet (mettendo da parte la mia app) 
ed il "bug" ï¿œ il solito.
 
Idee?
 
 
Questo ï¿œ il codice che ho trovato in rete:
 
 
 
 
 
/* Sample TCP server */
 
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
 
int main(int argc, char**argv)
{
    int listenfd,connfd,n;
    struct sockaddr_in servaddr,cliaddr;
    socklen_t clilen;
    pid_t     childpid;
    char mesg[1000];
 
    listenfd=socket(AF_INET,SOCK_STREAM,0);
 
    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
    servaddr.sin_port=htons(32000);
    bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
 
    listen(listenfd,1024);
 
    for(;;)
    {
       clilen=sizeof(cliaddr);
       connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);
 
       if ((childpid = fork()) == 0)
       {
          close (listenfd);
 
          for(;;)
          {
             n = recvfrom(connfd,mesg,1000,0,(struct sockaddr 
*)&cliaddr,&clilen);
             sendto(connfd,mesg,n,0,(struct sockaddr 
*)&cliaddr,sizeof(cliaddr));
 
printf("-------------------------------------------------------\n");
             mesg[n] = 0;
             printf("Received the following:\n");
             printf("%s",mesg);
 
printf("-------------------------------------------------------\n");
          }
 
       }
       close(connfd);
    }
}

 *)&cliaddr,&clilen);
 
Il problema del loop infinito potrebbe essere dovuto a
 
n = recvfrom(connfd,mesg,1000,0
                              ^
______________________________|
 
prova a mettere al suo posto  MSG_WAITALL: la funzione
dovrebbe mettersi in attesa fino a quando non gli arriva
un altro messaggio completo.
 
sempre che il tuo sistema non abbia
 
#define MSG_WAITALL 0
 
allora non saprei cosa dirti: anche io sto dando fondo
a reminescenze di una ventina (abbondante) di anni fa... :-)
 
C:\>iao Angelo

 n = recvfrom(connfd,mesg,1000,0,(struct sockaddr*)&cliaddr,&clilen);
 
Così come è scritta la recvfrom() ritorna con zero quando il peer 
remoto viene disconnesso e il loop viene innescato continuamente 
fintanto che un nuovo peer ai connette.
 
Come suggerito usando il parametro MSG_WAITALL potrebbe risolvere. 
Anche se non è chiaro come si comporta quando un peer chiude.
 
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   < 
http://giovanni.homelinux.net/
 >
 

 Giovanni
 
Forse mi sono perso qualcosa, ma perchè sendto/recvfrom?
Capirei con l'udp, ma lui ha un socket SOCK_STREAM, cioè TCP, e quindi 
send/recv bastano e avanzano(*).
 
Quanto al ciclo: n=recvfrom(...) => se il client si disconnette, recv 
fallisce immediatamente ("client disconnesso"), printf(), send pure 
fallisce immediatamente(**), ciclo da capo(!).
 
 
Insomma, dovresti:
1) controllare n dopo la recv, e
2) signal(SIGPIPE, SIG_IGN) in un programma che usa socket, anche se qui 
in realtà non serve.
 
Mamma che sproloquio...
 
 
 
(*) Con un socket, se non sei su windows, send(..., 0) == write(...)
(**) E mandare un bel SIGPIPE al programma quando provi a scriverci, ma 
può darsi che non ti arrivi per un motivo un po' contorto: sendto(fd, 
mesg, -1, ...) legge che n vale -1; -1 convertito in size_t è il valore 
massimo di size_t, che è più del limite massimo consentito (SSIZE_MAX), 
e quindi "the result is implementation defined", ma nel tuo caso direi 
che ti restituisce "errore, #byte troppo alto" senza andare a toccare il 
socket.

 
 > Quanto al ciclo: n=recvfrom(...) => se il client si disconnette, recv
 > fallisce immediatamente ("client disconnesso"), printf(), send pure
 > fallisce immediatamente(**), ciclo da capo(!).
 >
 >
 > Insomma, dovresti:
 > 1) controllare n dopo la recv, e
 > 2) signal(SIGPIPE, SIG_IGN) in un programma che usa socket, anche se qui
 > in realtà non serve.
 
ok...ti seguo fino ad un certo punto....ma seguendo il tuo ragionamento, 
perchè non entra subito in loop anche quando non invio niente?
in pratica basterebbe che controllassi che n>0 proseguo con la sendto 
etc...fino all'ultima printf("--------------"); giusto?
 
mò provo...
 
 


 
Ok

Il 13/09/2012 18:24, Lorenzo Beretta ha scritto:> On 12/09/2012 21:21, 
MB339A wrote:
 >>
 >>  (...)
 >>
 >> ok...ti seguo fino ad un certo punto....ma seguendo il tuo ragionamento,
 >> perchè non entra subito in loop anche quando non invio niente?
 > Non capisco, in che senso "quando non invio niente"? (se intendi prima
 > che un client si connetta è perchè si blocca sulla accept())
 
intendevo al momento della connessione da parte del client
 
 >
 >> in pratica basterebbe che controllassi che n>0 proseguo con la sendto
 >> etc...fino all'ultima printf("--------------"); giusto?
 >>
 >> mò provo...
 >>
 >>
 >
 > Ok
 
ho messo un semplice controllo if(n>0) e funge....
Speriamo di non aver incappato in qualche memory leak :)
 
Grazie tante a tutti quanti!
 

 aver incappato in qualche memory leak :)
 
In questo modo hai eliminato le inutili printf() ma non hai impedito 
di bloccare il loop fintanto che non si connette un nuovo cliente.
