Visualizzazione dei risultati da 1 a 5 su 5
  1. #1
    Utente di HTML.it
    Registrato dal
    Mar 2001
    Messaggi
    117

    [C/C++ - Linux] Evitare pacchetti spezzati nella trasmissione socket TCP

    Salve...! Ho un piccolo problema.
    Sto programmando in C/C++ sotto Linux e sto utilizzando i socket TCP per fare un semplice programmino client/server. Vi faccio vedere il codice:

    client
    codice:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <strings.h>
    #include <netinet/in.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    
    #define PORTASERVER 6000
    #define MAXBUFF 10000
    
    int main(int argc,char *argv[])
    {
    	FILE *fp;
    	struct hostent *hp;
    	struct sockaddr_in sin;
    	char *host;
    	char buf[MAXBUFF]="12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890";
    	int s;
    	int len;
    
    	if (argc==2)
    	{
    		host=argv[1];
    	}
    	else
    	{
    		fprintf(stderr,"usage: simplex-talk host\n");
    		exit(1);
    	}
    
    	hp=gethostbyname(host);
    	if (!hp)
    	{
    		fprintf(stderr,"simplex-talk: unknown host: %s\n",host);
    		exit(1);
    	}
    
    	bzero((char *)&sin,sizeof(sin));
    	sin.sin_family=AF_INET;
    	bcopy(hp->h_addr,(char *)&sin.sin_addr,hp->h_length);
    	sin.sin_port=htons(PORTASERVER);
    
    	if ((s=socket(PF_INET,SOCK_STREAM,0))<0)
    	{
    		perror("simplex-talk: socket");
    		exit(1);
    	}
    
    	if (connect(s,(struct sockaddr *)&sin,sizeof(sin)) <0)
    	{
    		perror("simplex-talk: connect");
    		close(s);
    		exit(1);
    	}
    
    		buf[MAXBUFF-1]='\0';
    		len=strlen(buf)+1;
    		send(s,buf,len,0);
    		printf("Lunghezza messaggio inviato: %i\n",len);
    
    
    	return 0;
    }
    server
    codice:
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <strings.h>
    #include <netinet/in.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netdb.h>
    
    
    #define PORTASERVER 6000
    #define MAXBUFF	10000
    #define MAXCONN	10
    
    
    int main()
    {
    	struct sockaddr_in sin;
    	char buf[MAXBUFF];
    	int len;
    	int s,new_s;
    
    	bzero((char*)&sin,sizeof(sin));
    	sin.sin_family=AF_INET;
    	sin.sin_addr.s_addr=INADDR_ANY;
    	sin.sin_port=htons(PORTASERVER);
    
    	if ((s=socket(PF_INET,SOCK_STREAM,0))<0)
    	{
    		perror("simplex-talk: socket");
    		exit(1);
    	}
    
    	if (bind(s,(struct sockaddr*)&sin,sizeof(sin))<0)
    	{
    		perror("simplex-talk: bind");
    		exit(1);
    	}
    	listen(s,MAXCONN);
    
    	while (1)
    	{
    		if ((new_s=accept(s,(struct sockaddr *)&sin,(socklen_t *)&len))<0)
    		{
    			perror("simplex-talk: accept");
    			exit(1);
    		}
    
    		while (len=recv(new_s,buf,MAXBUFF,0))
    		{
    			fputs(buf,stdout);
    			printf("\nLunghezza messaggio ricevuto: %i\n",len);
    		}
    		close(new_s);
    	}
    
    	return 0;
    }
    La cosa bizzarra che accade è che il messaggio inviato, che è di 8000 caratteri (più uno ulteriore per il terminatore) viene a volte (ma non sempre) spezzato in più messaggi, per cui in ricezione non visualizzo l'output tutto intero, ma viene prima rilevato un messaggio (tra l'altro senza terminatore, ma non è questo il punto) e poi un'altro. Non so se ciò avviene per qualche limite del buffer di invio della mia macchina o per qualche limitazione del protocollo. So ovviamente che il protocollo può spezzare i pacchetti, ma pensavo che la cosa fosse trasparente al programma, ovvero che il programma ricevesse un messaggio con la recv solo alla ricezione di un pacchetto completo.
    Esiste qualche soluzione nota per problemi di questo tipo, o mi devo inventare io qualcosa per gestire questo spezzettamento? (spezzettamento che, a quanto sembra, non ha una dimensione prevedibile)
    Questa cosa mi sta facendo sbattere la testa non poco...

    Grazie.

  2. #2
    Utente di HTML.it
    Registrato dal
    Mar 2001
    Messaggi
    117
    UP

  3. #3
    Utente di HTML.it
    Registrato dal
    Mar 2001
    Messaggi
    117
    Cercando in giro, ho provato a settare il bit DF di ip, in modo da dirgli di non frammentare il pacchetto:
    codice:
    	int val=IP_PMTUDISC_DO;
    	if (setsockopt(s, IPPROTO_IP,IP_MTU_DISCOVER, &val, sizeof(int)))
    Tuttavia non è cambiato nulla.

  4. #4
    Purtroppo quando mandi dei dati il client li scrive sul socket, poi vengono inviati al server che riceve e tramite recv() leggi solo i dati che attualmente si trovano sul socket. Non puoi mai sapere quanti byte leggerai, dipende dalla velocità con la quale leggi questi dati e con la velocità con cui arrivano.

    Puoi mandare un long (4 byte) all'inizio dove metti i byte che manderai (4 byte li dovrebbe mandare tutt'insieme(al 99,999%), certo non sarai mai certo, si tratta sempre di una trasmissione bit per bit) e leggere quei byte prima di ritornare il buffer.

  5. #5
    Utente di HTML.it
    Registrato dal
    Mar 2001
    Messaggi
    117
    Lolide, ti ringrazio per il tuo intervento. (ormai quasi non ci speravo più che qualcuno mi rispondesse)

    Sì, infatti stavo pensando proprio di fare qualcosa di questo tipo, ovvero mettere un numero all'inizio indicante la lunghezza del resto del messaggio, così lato ricezione, tramite il valore restituito da recv, vedo se ho ricevuto effettivamente tutti i dati; ricostruisco il vettore finché non ricevo tutti i dati e, solo allora, lo stampo. Credo che ormai sia l'unica soluzione.



    In ogni caso, se qualcuno conosce qualche soluzione migliore o più agevole (tipo settare qualcosa per far si che lo spezzettamento non avvenga, o qualsiasi altra cosa) rimango tutto orecchi.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.