[C] Write che non scrive su socket il giusto numero di byte

di il
4 risposte

[C] Write che non scrive su socket il giusto numero di byte

Ciao ragazzi, sono nuovo e spero di aver scritto nella sezione giusta.

Ho scritto un'applicazione client server, quest'ultimo multithread. Entrambi comunicano tramite socket AF_UNIX, usando le direttive write e read. Il mio problema è il seguente: una volta instaurata la connessione, se il client esegue la write sullo stdout di un certo numero di byte non c'è nessun problema, vengono scritti tutti i byte. Diversamente, se la stessa write viene fatta sul fd della connessione appena stabilita, il numero di byte scritti non è quello atteso ma inferiore.
Questo problema non si presenta nel caso del server, che scrive il messaggio di risposta come ci si attende, e il client lo riceve perfettamente, in quanto la read legge tanti byte quanti sono quelli che ci si aspetta.
Sapete per caso dirmi qualcosa su questa anomalia? Non riesco a capire da cosa sia dovuta, visto che si presenta solo quando è il client a dover inviare un messaggio, ed il messaggio viene scritto nella socket.

Dimenticavo: il client invia massimo 36544 byte, quindi se il messaggio che deve spedire ha una dimensione <= a questa, non esiste nessun problema.

Spero che qualcuno riesca ad aiutarmi, perchè non riesco a trovare una soluzione! Ringrazio in anticipo chiunque perderà tempo ad aiutarmi

4 Risposte

  • Re: [C] Write che non scrive su socket il giusto numero di byte

    Protocollo TCP/IP con SOCK_STREAM che gira su localhost? Potresti ciclare sui byte da spedire e controllare sul numero di byte spediti, oppure ciclare sui byte da ricevere e controllare sul numero di byte ricevuti per essere più sicuro
  • Re: [C] Write che non scrive su socket il giusto numero di byte

    Si, la comunicazione è SOCK_STREAM, ma solo il client dovrebbe ciclare, il server che usa la stessa funzione scrive tutti i byte di colpo.
    Praticamente se faccio fare la write su fd=1 (stdout) o su un fd associato ad un file aperto con la open() avviene la scrittura di tutti i byte che voglio. Diversamente, se faccio la stessa operazione sul fd che corrisponde alla socket connessa col server, la write scrive sempre e solo massimo 36544 byte. Se quindi la quantità di byte scritti è inferiore a questo massimo, non ci sono problemi, la comunicazione avviene perfettamente.
    Non capisco perchè fa questa distinzione, perchè con un valore fd si comporta in un modo e con un altro valore in un altro modo.
    Invece il server, che invia la risposta al comando ricevuto, riesce a scrivere perfettamente tutti i dati indipendentemente dalla loro dimensione.
  • Re: [C] Write che non scrive su socket il giusto numero di byte

    Posto qui il codice:

    Questa è la parte "interessante" del client
    int connfd;
        // faccio 10 tentativi aspettando 1 secondo
        if ((connfd=openConnection(spath, 10, 1))<0) {
    	fprintf(stderr, "error trying to connect...\n");
    	free(ops);
    	return -1;
        }
    La funzione openConnection è questa
    /**
     * @function openConnection
     * @brief Apre una connessione AF_UNIX verso il server membox.
     *
     * @param path Path del socket AF_UNIX 
     * @param ntimes numero massimo di tentativi di retry
     * @param secs tempo di attesa tra due retry consecutive
     *
     * @return il descrittore associato alla connessione in caso di successo
     *         -1 in caso di errore
     */
    int openConnection(char* path, unsigned int ntimes, unsigned int secs){
    
    	int retry;				/* conta il numero di tentativi di connessione */
    	int socket_fd;				/* fd della socket del client */
    	struct sockaddr_un socket_address;	/* indirizzo socket  */
    
    	/* controllo sui parametri ntimes e secs */
    	if( (ntimes > MAX_RETRIES) || (secs > 3) ){
    		fprintf(stderr, "Parametri non validi\n");
    		return -1;
    	}	
    
    	/* Preparo il sockaddr */
    	strncpy(socket_address.sun_path, path, sizeof(socket_address));
    	socket_address.sun_family = AF_UNIX;
    
    	/*  Creo la socket */
    	socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
    	if(socket_fd < 0){
    		perror("Errore aprendo la socket"); 
    		return -1;
    	}
    
    	retry = 0;
    	while(retry<ntimes){
    		if( connect(socket_fd, (struct sockaddr *) &socket_address, UNIX_PATH_MAX) == 0 )
    			return socket_fd;
    		else
    			sleep(secs);
    		retry++;
    	}
    	perror("Impossibile aprire una connessione col server");
    	return -1;
    }

    Una volta stabilita la connessione, il client fa questo:
        int r=0;
        for(int i=0;i<k;++i) {
    	r = execute_op(connfd, &ops[i]);
    	if (r == 0)  printf("Successo!\n\n\n---------------------------------------------------------------------\n\n");
    	else break;  // non appena una operazione fallisce esco
    	
    	static int execute_op(int connfd, operation_t *o) {
    	message_t msg;
        setData(&msg, NULL, 0);
        setHeader(&msg, op, &key);
        if (op == PUT_OP || op == UPDATE_OP) {
    	char *buf = malloc(size);
    	if (buf == NULL) {
    	    perror("malloc");
    	    return -1;
    	}
    	init_data(&key, buf, size);
    	setData(&msg, buf, size);
        } 
        printf("Il client ");
        if (sendRequest(connfd, &msg) == -1 && (errno != EPIPE)) {
    	perror("request");
    	return -1;
        }
     }
    	
    dove la sendRequest è così definita
    // ------- client side ------
    /**
     * @function sendRequest
     * @brief Invia un messaggio di richiesta al server membox
     *
     * @param fd     descrittore della connessione
     * @param msg    puntatore al messaggio da inviare
     *
     * @return 0 in caso di successo -1 in caso di errore
     */
    int sendRequest(long fd, message_t *msg){
    
    	int hdr, body;
    
    	printf("sta inviando il messaggio: key=%lu, op=%d, len=%d\n", msg->hdr.key, msg->hdr.op, msg->data.len);
    	hdr = write(fd, (struct message_t *) msg, sizeof(message_t));
    	if( hdr < 0){
    		perror("Problema nella scrittura del messaggio");
    		return -1;
    	}
    	if(msg->data.buf!=NULL){
    		body = write(fd, msg->data.buf, msg->data.len); 
    		if( body < 0){
    			perror("Problema nella scrittura dell'oggetto del messaggio");
    			return -1;
    		}
    	}
    	printf("Ho scritto %d byte di messaggio e %d byte di dati\n", hdr, body);	
        	return 0;
    }
    Questa stessa funzione, la sendRequest, viene usata dal server che fa esattamente quello che ci si aspetta.
  • Re: [C] Write che non scrive su socket il giusto numero di byte

    Do un occhiata appena posso. Sei costretto ad utilizzare read() e write() per la comunicazione?
Devi accedere o registrarti per scrivere nel forum
4 risposte