[C] TCP Server Client invio stringhe

di il
13 risposte

[C] TCP Server Client invio stringhe

Sto creando un programma in C per la comunicazione TCP tra un client e un server. Il client riceve da tastiera indirizzo e porta a cui connettersi (localhost su porta 9888 casuale) e una volta stabilita la connessione il server invia al client la stringa di connessione avvenuta.

1)Vorrei modificarlo per poter inserire nel client anzichè il nome "localhost" l'indirizzo numerico con utilizzo quindi della gethostbyaddr() suppongo. Come si può fare?

2)Dopodicheè dovrei anche leggere dal client sue stringhe A e B ed inviarle al server mediante una struct. Il server deve concatenarle in una stringa C = A + B e inviarla al client, aggiungendo la C alla struct iniziale ricevuta. Se una delle stringhe A o B è uguale a "quit", il server invia al client la stringa "bye". Quindi il client una volta ricevuta la stringa dal server e stampata, se questa è "bye" chiude la connessione e il programma termina, altrimenti torna a leggere due stringhe.

Il tutto con l'invio di due stringhe consecutive riuscirei a farlo credo, ma con la struct non so come procedere.
Grazie per l'aiuto!
//SERVER

#if defined WIN32
#include <winsock.h>
#else
#define closesocket close
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 30

void ClearWinSock() {
#if defined WIN32
    WSACleanup();
#endif
}

int main(void) {

//---------------------------INIZIALIZZAZIONE WSADATA

#if defined WIN32

    WSADATA wsaData;
    int iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf ("Error at WSAStartup");
        return 0;
    }

#endif

//-------------------------------CREAZIONE SOCKET

    int Mysocket;
    Mysocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

    //Valutare la presenza di errori per assicurarsi che la socket sia valida.
    if (Mysocket < 0) {
        printf("socket creation failed\n");
        return 0;
    }

    //Assegnazione indirizzo alla socket.
    struct sockaddr_in sad;
    memset(&sad, 0, sizeof(sad));
    sad.sin_family = AF_INET;
    sad.sin_addr.s_addr = inet_addr ("127.0.0.1");
    sad.sin_port = htons (9888);

//------------------------ASSEGNAZIONE PORTA E IP ALLA SOCKET

if (bind(Mysocket, (struct sockaddr*) &sad, sizeof(sad)) < 0) {
      printf ("bind() failed\n");
       closesocket(Mysocket);
       return 0;
}

//---------------------------SETTAGGIO SOCKET ALL'ASCOLTO

int qlen = 10; //numero client che il server può gestire

if (listen (Mysocket, qlen) < 0) {

    printf("listen() failed\n");
    closesocket(Mysocket);
    return 0;
}

struct sockaddr_in cad;  // struttura per l'indirizzo del cient
int Csocket;             // descrittore socket per il client
int clientlen;             // lunghezza indirizzo del client

//------------------------------ACCETTA LA CONNESSIONE

while (1) {

    printf("In attesa di un client con cui comunicare...\n");
    memset(&cad, 0, sizeof(cad));
    clientlen = sizeof(cad);       // assegna la dimensione dell'indirizzo del client

    if((Csocket = accept(Mysocket, (struct sockaddr*) &cad, &clientlen)) < 0) {
        printf ("accept failed\n");
        closesocket(Mysocket);
        ClearWinSock();
        return 0;
    }


    printf("Connessione stabilita con il client il cui indirizzo e' %s \n\n", inet_ntoa(cad.sin_addr));

//---------------------------------------INVIO STRINGA AL CLIENT

    char* inputString = "Connessione avvenuta!";
    int stringlen = strlen(inputString);


    if (send(Csocket, inputString, stringlen, 0) != stringlen) {
        printf("client-send() sent a different number of bytes than expected");
        closesocket(Csocket);
        ClearWinSock();
        system ("pause");
        return 0;
    }

//CLIENT

#if defined WIN32
#include <winsock.h>
#else
#define closesocket close
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 30

void ClearWinSock() {
#if defined WIN32
    WSACleanup();
#endif
}

//-----------------------------INIZIALIZZAZIONE WSADATA

int main (void) {
#if defined WIN32

    WSADATA wsaData;
    int iResult = WSAStartup (MAKEWORD (2,2), &wsaData);

    if (iResult !=0) {
        printf ("error at WSASturtup\n");
        return 0;
        }

#endif

//--------------------------------CREAZIONE SOCKET

    int Csocket;

    Csocket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (Csocket < 0) {

    printf ("socket creation failed");
    closesocket (Csocket);
    ClearWinSock();
    return 0;
    }

    char s_name[BUFSIZE];
            printf ("Inserisci il nome dell'host a cui connetterti\n");
            scanf ("%s", s_name);

            int port;
            printf ("Inserisci la porta a cui connetterti\n");
            scanf("%d", &port);


            struct hostent *host;
            host = gethostbyname(s_name);
            if (host == NULL) {
            fprintf(stderr, "gethostbyname() failed.\n");
            return 0;
            }

            struct sockaddr_in sad;
                memset (&sad, 0, sizeof(sad));
                sad.sin_family = AF_INET;
                sad.sin_addr.s_addr = *((long*) host->h_addr);
                sad.sin_port = htons (port);

//------------------------------CONNESSIONE AL SERVER

   if (connect(Csocket, (struct sockaddr*) &sad, sizeof(sad)) < 0) {
         printf ("failed to connect\n");
         closesocket (Csocket);
         ClearWinSock();
         return 0;
   }

//-----------------------------RICEZIONE STRINGA DAL SERVER

   char buf[BUFSIZE];

   int read = recv (Csocket, buf, BUFSIZE - 1, 0);

   if (read <=0) {

       printf ("Qualcosa non và!\n");
   }

   else {
       buf[read] = '\0';  //tappo stringa per sicurezza
       printf("Server scrive: %s\n", buf);
   }

13 Risposte

  • Re: [C] TCP Server Client invio stringhe

    Per l'inserimento di 127.0.0.1 anzichè localhost non riesco a capire come procedere.

    Per le stringhe sto provando così, ma mi dà errore sull'argomento 2 del send:

    struct stringab {
    char a[];
    char b[];
    } ab;


    void* abptr = &ab;

    char a[];
    printf ("Inserisci prima stringa");
    scanf ("%s", ab.a);

    char b[];
    printf ("Inserisci seconda stringa");
    scanf ("%s", ab.b);



    if (send(Csocket, (char*)abptr, sizeof(ab), 0) != sizeof(ab)) {
    printf("client-send() sent a different number of bytes than expected");
    closesocket(Csocket);
    ClearWinSock();
    system ("pause");
    return 0;
    }
  • Re: [C] TCP Server Client invio stringhe

    Gli array devono avere una dimensione ... e poi, perché ne definisci due locali? Devi usare quelli della struttura ...

    Per l'indirizzo, stavo rispondendo nell'altro forum ... ma rispondo qui, anche se postare in più forum fa solo confusione ...
    Non ho proprio capito ... nel codice hai già l'indirizzo, non il localhost ...
  • Re: [C] TCP Server Client invio stringhe

    Dunque, volevo che nel client mi chiedesse di inserire l'ip e non "localhost". Alla fine era più semplice di quello che sembrava e ho fatto così:

    char s_name[BUFSIZE];
    printf ("Inserisci l'indirizzo dell'host a cui connetterti\n");
    scanf ("%s", s_name);

    int port;
    printf ("Inserisci la porta a cui connetterti\n");
    scanf("%d", &port);

    struct sockaddr_in sad;
    memset (&sad, 0, sizeof(sad));
    sad.sin_family = AF_INET;
    sad.sin_addr.s_addr = inet_addr(s_name);
    sad.sin_port = htons (port);

    Quindi ho avvalorato la struttura direttamente con l'ip digitato e memorizzato nella stringa s_name.

    Per quanto riguarda la struttura: il client deve leggere due stringhe da std input e inviarle al server e non so come fare..
  • Re: [C] TCP Server Client invio stringhe

    mark9 ha scritto:


    Dunque, volevo che nel client mi chiedesse di inserire l'ip e non "localhost". Alla fine era più semplice di quello che sembrava
    Ma infatti ... era quello che ti dicevo. Non capisco perché chiami

    char s_name[BUFSIZE];

    il dato, visto che è un IP. Semmai

    char s_address[BUFSIZE];
    Per quanto riguarda la struttura: il client deve leggere due stringhe da std input e inviarle al server e non so come fare..
    Va bene la struttura, ma le stringhe, come ti ho già detto, devono avere una dimensione !
  • Re: [C] TCP Server Client invio stringhe

    Hai ragione, avevo lasciato il vecchio nome di variabile per utilizzarla con localhost, ho corretto.

    Quindi ora ho fatto così:

    struct stringab {
    char a[30];
    char b[30];
    } ab;


    void* abptr = &ab;


    printf ("Inserisci prima stringa");
    scanf ("%s", ab.a);


    printf ("Inserisci seconda stringa");
    scanf ("%s", ab.b);



    if (send(Csocket, (char*)abptr, sizeof(ab), 0) != sizeof(ab)) {
    printf("client-send() sent a different number of bytes than expected");
    closesocket(Csocket);
    ClearWinSock();
    system ("pause");
    return 0;
    }


    Ora dovrebbe chiedermi di inserire le due stringhe, metterle in struttura ed inviarle al server.

    Come opero sul server per fare questa operazione?

    "Il server riceve le stringhe A e B e le concatena in un'unica stringa C uguale ad “A + B” e la
    invia indietro al client, aggiungendo il valore C alla struct inizialmente ricevuta; altrimenti,
    se almeno una delle due stringhe A o B è uguale a “quit” il server invia al client la stringa
    “bye”."
  • Re: [C] TCP Server Client invio stringhe

    Aggiungi un'altra stringa alla struttura, una stringa c lunga abbastanza da contenere le prime due (non hai importanza cosa invii in questa stringa).

    Sul server ricevi i dati nella stessa struttura. Dopo la ricezione, controlla le stringhe a e b come indicato e, se contengono "quit" concludi il programma. Altrimenti, le unisci in c e reinvii al client.
  • Re: [C] TCP Server Client invio stringhe

    Come ricevo nel server con la recv() la struttura?
  • Re: [C] TCP Server Client invio stringhe

    Dato che usi Winsock, dovresti usare

    WSASend per inviare dati e WSARecv

    Dovresti leggere la documentazione su MSDN, in cui trovi anche esempi e ulteriori spiegazioni.
  • Re: [C] TCP Server Client invio stringhe

    Ho cambiato tutto in Winsock2 che è quella che effettivamente usavo ormai negli ultimi programmi, ricordo che fosse migliore della obsoleta winsock.
  • Re: [C] TCP Server Client invio stringhe

    Si, è uguale, intendevo la famiglia di api windows
  • Re: [C] TCP Server Client invio stringhe

    Ho risolto.
    @oregon: del crosspost non sapevo; su alcuni forum non ricevevo nessuna risposta perchè poco frequentati su certe tematiche e ho provato a chiedere altrove. La prossima volta eviterò.
    ps: avviso io o avvisi tu gli altri che ho risolto?
  • Re: [C] TCP Server Client invio stringhe

    No ... io non faccio nulla. Scrivi tu dove hai scritto e dai spiegazioni, se vuoi.

    Qui, invece, sarebbe il caso che, dopo tutta questa discussione dicessi come hai risolto, per altri che leggono ...
  • Re: [C] TCP Server Client invio stringhe

    Struttura inviata con send() e ricevuta con recv() con un puntatore a struttura in entrambi i casi. Penso sia una soluzione buona per il local hosting, mentre per la rete ci sono metodi più complessi e sicuri.
Devi accedere o registrarti per scrivere nel forum
13 risposte