2013-07-23 15 views
7

Pracuję nad programem klient/serwer, a mój klient musi wysyłać wiadomości na serwer.Wyślij struct over socket do C

Przykładowa wiadomość C struktura:

struct Registration 
{ 
char multicastGroup[24]; 
pid_t clientPid; 
}; 

Client fragment kodu do serializacji struct

struct Registration regn ; 
regn.clientPid = getpid(); 
strcpy(regn.multicastGroup, "226.1.1.1"); 

printf("PID:%d\n", regn.clientPid);   
printf("MG:%s\n", regn.multicastGroup); 
printf("Size:%d\n", sizeof(regn));   //Size is 28 

data = (unsigned char*)malloc(sizeof(regn)); 
memcpy(data, &regn, sizeof(regn)); 
printf("Size:%d\n", sizeof(data));   //Size is 4. 

kod serwera de-serializacji danych

if(recvfrom(sd, recvBuf, recvBufSize, 0, (struct sockaddr*)&clientAddr, &len) < 0) 
{ 
     printf("Error receiving message from client\n"); 
} 
else 
{ 
     printf("Message received:%s\n", recvBuf); 
     printf("Size :%d\n", strlen(recvBuf)); 
     memcpy(&regn, recvBuf, sizeof(regn)); 
     printf("PID:%d\n", regn.clientPid); 
     printf("MG:%s\n", regn.multicastGroup); 
} 

Po skopiowaniu struktury do unsigned char * rozmiar tablicy wynosi tylko 4.
Dlaczego dane nie są w pełni skopiowane do tablicy?

Serwer nie może zrekonstruować struktury z tablicy char.
Proszę dać mi znać, co robię źle.

Odpowiedz

10

sizeof(regn) daje rozmiaru całej konstrukcji Registration, ubezpieczeniowy sizeof(data) jest wielkość wskaźnika na komputerze, który jest 4 bajty (data powinien być wskaźnik od Registration typu).

W wyrażeniem:

memcpy(data, &regn, sizeof(regn)); 
     ^ ^
     |  value variable of struct type 
     is pointer 

również zauważyć w printf . służy do łączenia elementów np regn.multicastGroup.

+0

Chcę wysłać te dane przez gniazdo. Stąd jestem 'memcpy' to na' unsigned char * ' – cppcoder

+0

@cppcoder której używasz funkcji, jeśli zajmuje ona rozmiar przechowywanych danych, to powinieneś użyć' sizeof (struct Registration) ' –

+0

@cppcoder czy używasz' sendto() '? z C –

3

Podczas gdy kod zadziała, jeśli wyślesz i odwiedzisz na tej samej maszynie endianowej - twój klient i serwer powinien idealnie wykonać host do konwersji endianów sieciowych, aby zachować spójność podczas inspekcji clientPid.

+0

Czy możesz pokazać, jak wykonać 'htonl' na zmiennej podczas wysyłania? – cppcoder

0

Ze względu na przenośność, dobrą praktyką jest szeregowanie każdego elementu konstrukcyjnego indywidualnie ze względu na specyficzne dla danej platformy wykończenie i dopełnienie struktury.

Oto przykład przy użyciu Binn:

binn *obj; 

    // create a new object 
    obj = binn_object(); 

    // add values to it 
    binn_object_set_int32(obj, "clientPid", getpid()); // assuming it is 32 bits 
    binn_object_set_str(obj, "multicastGroup", "226.1.1.1"); 

    // send over the network 
    send(sock, binn_ptr(obj), binn_size(obj)); 

    // release the buffer 
    binn_free(obj); 

To jest zaledwie 2 pliki (binn.c i binn.h), więc może być zestawiane w ramach projektu zamiast stosować jako udostępnionej biblioteki.

Być może powinieneś również użyć ramek komunikatów (zwanych również ramkami prefiksów długości) w strumieniach gniazd, aby uniknąć koalescencji i fragmentacji wiadomości.