serializacja c++

0

Hej, chce przesylac obiekty(powiedzmy ze w tym obiekcie bedzie tablica znakow oraz jakas zmienna int) pomiedzy klientem i serverem operacja send, no i moje pytanie jak je zamienic na ciag bitow, oraz jak uzyc pozniej metody send na nich?

celem powyzszego pytania jest, przesylanie do servera danych, oraz zeby owe dane byly rozrozniane. Przy pierwszym polaczeniu klient bedzie musial wyslac "swoje dane ktore beda mowily powiedzmy (kim jest i skad pochodzi)" , zas server bedzie rozroznic czy przychodzace do niego dane to komunikat wysylany przez clienta przy polaczeniu czy zwykla wiadomosc do servera .. Przepraszam ze tak chaotycznie ale jestem w tym nowy.

2

Najprostszy wariant, to po prostu (jeśli obiekt nie zawiera typów jak std::string) zrzutować na void* i wysłać.

struct s
{
char txt[508];
int num;
} __attribute__((packed)); /** Żeby kompilator nie paddingował, bo po co **/
s x;
send(sock, static_cast<void*>(&x), sizeof(x));

Pamiętaj tylko o konwersji do sieciowej kolejności bajtów (big-endian, i potem w kliencie/serverze do swojej kolejności), a potem sobie to odbierz tak:

/** Ta sama struktura **/
s x;
recv(sock, static_cast<void*>(&x), sizeof(x));

Jak planujesz coś bardziej skomplikowanego, zainteresuj się tym

3

Przy większych projektach mogę polecić protobuf (EDIT: tak samo jak Proxima wyżej, czego nie zauważyłem, ups) - ma kilka zalet nad powyższym rozwiązaniem, np.

  1. Nie masz wycieków niezainicjalizowanej pamięci jak w powyższym przykładzie ;)
  2. Jest endian-independent.
  3. Możesz łatwo wygenerować klasy dekodujące/kodujące do kilku różnych języków, co zwiększa przenośność.
  4. Dostajesz gratis sprawdzanie czy na pewno wszystkie istotne pola zostały wypełnione.

Jest też kilka wad:

  1. Musisz dodatkowo odpalić "kompilator protobuf", który wygeneruje Ci na podstawie definicji pakietu (pliku .proto) klasy w C++ / innych językach.
  2. No i jak ze wszystkim - trzeba się do tego przyzwyczaić.

(Jeśli robisz coś w stylu RPC, to protobufy też można do tego użyć - http://www.grpc.io/docs/)

3

Protobuf jest fajny ale nie zawsze można/chcemy bawić się w generowanie właściwego kodu na podstawie plików .proto (zwłaszcza, gdy część systemu pisania jest języku x, część w y a jeszcze inna w z (który akurat potrzebuje kolejnej zewnętrznej liby żeby w ogóle wygenerować srcs).
Możesz za to np. serializować do JSONa albo jeśli nie zależy Ci na dużej wydajności ale za to chcesz w prosty sposób serializaować i deserializować swoje klasy w C++ to użyj boost::serialization (btw i tak polecałbym użyć w takim przypadku jakiejś liby z JSONem, bo użycie może być jeszcze prostsze niż boost::serialization, np. https://github.com/nlohmann/json).

0

Proxima a co jesli pobieram znaki do bufora char msg[length] a pozniej chce to wrzucic do struktury i przeslac w taki sposob jak podales powyzej(wiem ze moe uzyc char tab[500] jednak chce zeby wielkosc tekstu wpisana w strukture byla zmienna)?? musze zadzialac jakos operatorem new?

1

Dynamicznie alokujesz pamięć na wiadomość operatorem new bądź malloc, przed wysłaniem struktury wysyłasz do klienta wielkość wiadomości, aby wiedział ile danych ma odebrać. Tylko pamiętaj aby tą pamięć zwolnić :)
Chociaż IMO dynamiczna alokacja może tu być uciążliwa, i proponuje Ci użyć stringa. (sprawdź metody c_str() i length())

0

ok a co myslisz o tym zeby moje zmienne i bufor umiescic w dynamicznie utworzonej tablicy znakow i ja wyslac? zamiast przekazywania calej struktury ^-* hmm i jak wrzuc zmienna int int char[] do jednej tablicy znakow :(

0

Inty do tablicy charów możesz wpisać różnie, przykładowo, dla stałej i niewielkiej liczby intów, użyj funkcji snprintf.
Jak dane będą pobierane od klienta i wpisze za dużo, to grozi ci buffer overflow w kliencie, dlatego użyj właśnie snprintf i ustal limit wielkości bufora.
Inny sposób to użyć stringa, operatora += i std::to_string.
Możesz także użyć lexical_cast z boosta, sposobów masz wiele, wybierz nawygodniejszy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1