2014-07-02 5 views
8

Ho un'applicazione client-server.Più chiamate a send() sono unite in una chiamata a recv()

Il client invia una stringa seguita da un numero intero utilizzando due chiamate distinte send(). Questi due dati dovrebbero essere memorizzati in due diverse variabili sul server.

Il problema è che entrambe le variabili inviate sono ricevute alla chiamata recv(). Pertanto, le due stringhe inviate dai due distinti send() s vengono concatenate e memorizzate nel buffer del primo recv().

server.c:

printf("Incoming connection from client %s:%i accepted\n",inet_ntoa(clientSocketAddress.sin_addr),ntohs(clientSocketAddress.sin_port)); 


memset(buffer,0,sizeof(buffer)); 
int sizeofMessage; 
if ((recv(clientSocket,buffer,MAXBUFFERSIZE,0)==sizeofMessage)<0) 
{ 
    printf("recv failed."); 
    closesocket(serverSocket); 
    clearWinsock(); 
    return EXIT_FAILURE; 
} 

char* Name=buffer; 
printf("Name: %s\n",Name); 

if ((recv(clientSocket,buffer,MAXBUFFERSIZE,0))<0) 
{ 
    printf("bind failed."); 

    closesocket(serverSocket); 
    clearWinsock(); 
    return EXIT_FAILURE; 
} 

int integer=ntohs(atoi(buffer)); 
printf("integer: %i\n",intero); 

client.c:

if (send(clientSocket,Name,strlen(Name),0)!=strlen(Name)) 
{ 
    printf("send failed"); 

    closesocket(clientSocket); 
    clearWinsock(); 
    return EXIT_FAILURE; 
} 

printf("client send: %s",Name); 

int age=35; 
itoa(htons(age),buffer,10); 
sizeofBuffer=strlen(buffer); 
if (send(clientSocket,buffer,sizeofBuffer,0)!=sizeofBuffer) 
{ 
    printf("bind failed."); 

    closesocket(clientSocket); 
    clearWinsock(); 
    return EXIT_FAILURE; 
} 

Come posso risolvere il problema? Che cosa sto facendo di sbagliato?

risposta

7

TCP è un protocollo di streaming. Non è a conoscenza di alcun tipo di limiti di "messaggio". Non aggiunge tali informazioni a seconda delle singole chiamate a send().

A causa di questi fatti. Qualsiasi numero di send() s sul lato del mittente può portare a un numero qualsiasi di recv() s (fino al numero di byte inviati) sul lato ricevitore.

Per aggirare questo comportamento, definire e implementare un protocollo a livello di applicazione per distinguere i diversi "messaggi" che erano stati inviati.

Non si può fare affidamento su recv()/send() ricevere/inviare tanti byte quante sono state dette a ricevere/inviare da quelle due funzioni. È essenziale verificare il loro valore di ritorno per sapere quanti byte hanno effettivamente ricevuto/inviato tali funzioni e aggirarle intorno finché tutti i dati che si desidera ricevere/inviare siano stati ricevuti/inviati.

Per esempi come questo "looping" potrebbe essere fatto

1

Ecco come funziona TCP. Tratta come un flusso di byte. Metti sopra del protocollo di base - delimita i messaggi dell'applicazione con qualche valore di byte noto, o anteponi i tuoi messaggi con il campo della lunghezza.

Oppure passare a UDP, che fornisce la semantica del datagramma che si sta cercando, se è possibile tollerare/recuperare dalla perdita occasionale di pacchetti.

+0

" delimitare i messaggi dell'applicazione con qualche valore di byte noto "solo per chiarire, questo è chiamato protocollo, alcune persone usano qualcosa come questo STXyourmessageETXXOR dove STX (start) in HEX è 2, ETX (END) in HEX è 3, e XOR è un bit operazione^per STXyourmessageE TX, risultato = STX^y -> risultato^= u ... dove XOR rappresenta la cifra per la verifica –

Problemi correlati