Socket C -Scambio messaggi

di il
3 risposte

Socket C -Scambio messaggi

Buonasera, è da poco che sto programmando con i socket e non riesco a capire dove è il mio sbaglio. Il programma dovrebbe fare questo:
- Il client inserisce da riga di comando una stringa e un numero (che sarà il numero X di volte che verrà inviata la stringa al server).
-Il server riceve nel suo buffer la stringa moltiplicata X volte e risponde al client semplicemente con al stringa (una sola volta)
-Il client stampa "Input X e stringa Y".

Questo è quello che ho provato a fare.

Server:
#include <stdio.h>      
#include <sys/types.h>
#include <sys/socket.h>   
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define PORTA "11000"
#define MAXLINE 256

int main() {
    int conta=0;
    char buffer[256]="";
    int simpleSocket = 0;
    int simplePort = 0;
    int returnStatus = 0;
    int returnMessage = 1;
    struct sockaddr_in simpleServer;

    simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (simpleSocket == -1) {

        fprintf(stderr, "Could not create a socket!\n");
        exit(1);

    }
    else {
	    fprintf(stderr, "Socket created!\n");
    }

    /* retrieve the port number for listening */
    simplePort = atoi(PORTA);

    /* setup the address structure */
    /* use INADDR_ANY to bind to all local addresses  */
    memset(&simpleServer, '\0', sizeof(simpleServer)); 
    simpleServer.sin_family = AF_INET;
    //simpleServer.sin_addr.s_addr = htonl(INADDR_ANY);
    simpleServer.sin_addr.s_addr = htonl(INADDR_ANY);
    simpleServer.sin_port = htons(simplePort);

    /*  bind to the address and port with our socket  */
    returnStatus = bind(simpleSocket,(struct sockaddr *)&simpleServer,sizeof(simpleServer));

    if (returnStatus == 0) {
	    fprintf(stderr, "Bind completed!\n");
    }
    else {
        fprintf(stderr, "Could not bind to address!\n");
	close(simpleSocket);
	exit(1);
    }

    /* lets listen on the socket for connections      */
    returnStatus = listen(simpleSocket, 5);

    if (returnStatus == -1) {
        fprintf(stderr, "Cannot listen on socket!\n");
	close(simpleSocket);
        exit(1);
    }

    while (1)

    {

        struct sockaddr_in clientName = { 0 };
	int simpleChildSocket = 0;
	int clientNameLength = sizeof(clientName);

	/* wait here */

        simpleChildSocket = accept(simpleSocket,(struct sockaddr *)&clientName, &clientNameLength);

	if (simpleChildSocket == -1) {

            fprintf(stderr, "Cannot accept connections!\n");
	    close(simpleSocket);
	    exit(1);

	}
	/* get the message from the client   */
	while(returnMessage>0){
	  returnMessage = read(simpleChildSocket, buffer, sizeof(buffer));
	  //printf("dentro al server %d: %s\n", returnMessage, buffer);
	  //memset(&buffer, '\0', MAXLINE); 
	  conta++;
	}
	write(simpleChildSocket, &conta, 1);
	write(simpleChildSocket, buffer, strlen(buffer));
	memset(&buffer, '\0', MAXLINE); 
        close(simpleChildSocket);

    }

    close(simpleSocket);
    return 0;

}
Client:
#include <stdio.h>      
#include <sys/types.h>
#include <sys/socket.h>   
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define INDIP "192.168.2.5"
#define PORTA "11000"
#define MAXLINE 256

int main() {
    char s[256]="";
    int Nstringhe=0;
    int simpleSocket = 0;
    int simplePort = 0;
    int returnStatus = 0;
    int messaggio=1;
    char buffer[256] = "";
    struct sockaddr_in simpleServer;

    /* create a streaming socket      */
    simpleSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (simpleSocket == -1) {

        fprintf(stderr, "Could not create a socket!\n");
        exit(1);

    }
    else {
	    fprintf(stderr, "Socket created!\n");
    }

    /* retrieve the port number for connecting */
    simplePort = atoi(PORTA);

    /* setup the address structure */
    /* use the IP address sent as an argument for the server address  */
    //bzero(&simpleServer, sizeof(simpleServer)); 
    memset(&simpleServer, '\0', sizeof(simpleServer));
    simpleServer.sin_family = AF_INET;
    //inet_addr(argv[2], &simpleServer.sin_addr.s_addr);
    simpleServer.sin_addr.s_addr=inet_addr(INDIP);
    simpleServer.sin_port = htons(simplePort);

    /*  connect to the address and port with our socket  */
    returnStatus = connect(simpleSocket, (struct sockaddr *)&simpleServer, sizeof(simpleServer));

    if (returnStatus == 0) {
	    fprintf(stderr, "Connect successful!\n");
    }
    else {
        fprintf(stderr, "Could not connect to address!\n");
	close(simpleSocket);
	exit(1);
    }
    printf("Quante volte vuoi inviare il messaggio? : ");
    scanf("%d\n",&Nstringhe);
    printf("Inserire la stringa: ");
    gets(s);
    while(Nstringhe>0){ 
      /* write out our message to the server */
      write(simpleSocket, s, strlen(s));
      Nstringhe--;
    }
    /*get the message from the server*/
    messaggio = read(simpleSocket, buffer, sizeof(buffer));

    if ( messaggio > 0 ) {
        printf("client %d: %s", messaggio, buffer);
    } else {
        fprintf(stderr, "Return client Status = %d \n", messaggio);
    }
    memset(&buffer, '\0', MAXLINE);
    close(simpleSocket);
    return 0;

}
Se mi riuscite a dare una dritta mi fareste un grandissimo favore, perchè sono proprio bloccato.
Grazie
Ciao!

3 Risposte

  • Re: Socket C -Scambio messaggi

    Ma cosa succede con il ruo codice? Non hai detto dove sta il problema
  • Re: Socket C -Scambio messaggi

    Le socket sono una rogna rognosa: la prima cosa che devi imparare e' che la socket classica funziona in modalita' stream, cioe' NON C'E' il concetto di messaggio.

    Questo vuol dire che da nessuna parte ti e' assicurato che se tu invii 100 byte, dall'altra parte ti arrivano ESATTAMENTE 100 byte:

    - te ne possono arrivare 10/90, 50/50, 33/67 o qualunque altra strana divisione
    - il driver della scheda di rete potrebbe ANCHE concatenare PIU' messaggi e spezzare l'ultimo in un punto qualunque.
    - questo NON VUOL DIRE che non riceverai MAI 100 byte: infatti spesso accade proprio cosi' perche' entrano in gioco i timeout di svuotamento del buffer della scheda di rete, MA NON E' ASSICURATO! E questo dipende anche dalla VELOCITA' con cui invii i messaggi e dalla loro DIMENSIONE!

    Quindi devi essere TU a' introdurro il concetto di MESSAGGIO: in generale lo fai aggiungendo un HEADER ed un FOOTER al messaggio che devi inviare, dove nell'HEADER c'e' ALMENO la lunghezza del messaggio, e magari qualche MAGIC NUMBER (replicato nel FOOTER) per assicurarti che stai effettivamente leggendo un messaggio completo e non ti trovi in mezzo a un messaggio qualunque (nel qual caso la lunghezza e' ovviamente SBAGLIATA)

    In ricezione devi assicurarti di leggere lo HEADER, il numero corretto di byte e il FOOTER.

    Tieni presente che la dimensione massima del blocco di byte inviati da una scheda di rete dovrebbe essere 64K byte. Quindi il tuo messaggio non dovrebbe MAI superare i 65000 byte. Se devi inviare un messaggio piu' lungo, lo DEVI spezzare in piu' messaggi di AL PIU' 65000 byte!
  • Re: Socket C -Scambio messaggi

    Non mi ero accorto che non avevo scritto il mio output.
    - Si stabilisce la connessione lato server e client
    - Il client chiede "Quante volte voglio inviare il messaggio?" e metto per esempio 3 (salvando il valore in una variabile con Scanf)
    - Il client chiede la stringa e qui c'è il primo errore: non mi esce la printf con la domanda! Io però inserisco lo stesso una stringa sapendo che c'è il gets(stringa) subito dopo. E da qui il client non mi da più risposte/segnali, è andato in loop, come se fosse in attesa di altri dati, mi obbliga a forzare l'uscita.
    - Una volta forzata l'uscita del Client allora il server termina l'esecuzione (prima era rimasto sempre in attesa di altri valori). Ho inserito una printf per vedere se il server ha ricevuto le 3 stringhe uguali dal client e così è stato però non ha rinviato al client il messaggio di risposta con una stringa sola.

    Quindi ricapitolando il programma dovrebbe fare così: Il client invia 3 stringhe (per esempio 3 ciao) al server. Il server riceve le 3 stringhe e risponde al client con un "ciao". Il client riceve il ciao e lo stampa a video.
    Ho provato anche a usare la fgets(s,strlen(s),stdin) al posto della gets(s) nel client ma niente da fare anzi peggiora l'output: il server non stampa niente, come se non ricevesse manco una stringa.
    Esistono mica incompatibilità tra Scanf e gets o fgets? Perchè secondo me il problema è proprio qua (magari mi sbaglio).

    Mi sono accorto che le socket non sono così intuitive come pensassi...o almeno all'inizio.
    Ciao e Grazie!!!
Devi accedere o registrarti per scrivere nel forum
3 risposte