Jump to content
SqRobert

C++ Working with bytes

Recommended Posts

As vrea si eu un ghid clar sau niste exemple cum as putea sa stochez date in cate un byte sau daca pot concatena la un char* pentru ca la finaltrebuie sa-l transmit prin parametru char*.

int sendto(
_In_ SOCKET s,
_In_ const char *buf,
_In_ int len,
_In_ int flags,
_In_ const struct sockaddr *to,
_In_ int tolen
);

Intentia mea e sa creez un sir lung de bytes cu date de tip , string , int , long , enum orice tip sa il pot stoca in cate un byte sau mai multi daca depaseste capacitatea si adaugat la un sir intreg

Link to comment
Share on other sites

Nu e asa simplu sa faci asta. Problema principala e urmatoarea, cum iti dai seama unde incepe si unde se termina o variabila si incepe alta in sir-ul tau?

Daca ai date de transmis prin retea, atunci cel mai ok ar fii sa trimiti datele pe rand.

Daca e vorba de vreun struct/class atunci trimiti membri, iar la celalalt capat ii citesti si construiesti un nou obiect(struct sau class).

Trebuie insa sa tii cont de cum ajung datele, trebuie sa gasesti si acolo o metoda sa delimitezi ce trimiti, cand trimiti.

Eu in general incerc sa fac ceva gen pachete, verific daca ce am de transmis e mai mare de 255 bytes. Daca nu este, trimit 0 pentru ca este mai mic decat 255 si dupa trimit numarul de bytes pe care trebuie sa ii citesc, dupa care trimit ce am de trimis.

Daca am mai mult de 255 bytes, trimit numarul de block-uri de 255 bytes(spre exemplu am 1024 bytes de transmis), in cazul asta 4, urmat de numarul de bytes ramasi de transmis(4).

Ambele numere le transmit sub forma de unsigned char(poate sa contina valori de la 0 la 255) iar cand le primesc le transform in int.

Nu stiu daca e cea mai eficienta solutie sau cea mai buna, dar la ultimele programe la care am lucrat cu sockets, asa am facut si mi-a mers bine.

  • Downvote 1
Link to comment
Share on other sites

Nu vreau si nu pot sa folosesc inca structuri sau clase, merg treptat.

Mesajul il recunosc dupa NetworkMessageType.

enum NetworkMessageType
{
NetworkMessageType_Invalid = 1,
NetworkMessageType_Join = 2,
NetworkMessageType_UpdateFromClient_Input = 4,
NetworkMessageType_UpdateFromServer_Input = 8,
};

Actual pentru setarea mesajului folosesc asta

*reinterpret_cast<NetworkMessageType*>(m_Buffer) = NetworkMessageType_Join;

Pe viitor o sa adaug in primul byte 8 mesaje folosing bit flags sau primi doi bytes in functie de cat voi avea nevoie. urmat de numarul de bytes ocupat de informatia de urmeaza.

buff[0] = NetworkMessageTypes
buff[1] = 2 next bytes used (Message Type Position)
buff[2] = position.x
buff[3] = position.y
buff[4] = 8 bytes used (Message Type Position(X,Y) 4 enemies)

1. Cum adaug 1024 intr-un byte?

2. E bine sa folosesc un array de char-uri?

Daca da cum transform 1

short int

intr-un singur byte daca stiu clar ca nu depasesc acea memorie? Ma folosesc de bitwise operators?

Am gasit un exemplu

Exemplu:

 char myChar[20];
unsighed short s_int = 800;

myChar[0] = s_int -->convert 1 byte of short int into char;

Ce am gasit. Asta imparte cei 2 bytes in cate un char.


buff[0] = s_int & 0xff;
buff[1] = (s_int >> 8) & 0xff;

3:Ce reprezinta?

 0xff

?

Nu am gasit prea multe pe google. Multumesc ,apreciez ajutorul oferit!

Link to comment
Share on other sites

Cat despre transformat din tipuri fundamentale(int, double, float) in char, folosesti reinterpret_cast si marimea tipului.

Spre exemplu:


#include <iostream>
#include <cstring>
using namespace std;


int main() {

unsigned char* bts = new unsigned char[sizeof(double)]; // char array de marimea unui double
double d = 123.45; // double-ul nostru
memcpy(bts, &d, sizeof(double)); // copiem la adresa lui bts continutul adresei &d continand sizeof(double) bytes
cout << bts << endl; // printam continutul array-ului bts
double dd;
memcpy(&dd, bts, sizeof(double)); // copiem la adresa lui dd continutul array-ului bts cu marimea sizeof(double) bytes
cout << dd;

return 0;
}

0xff inseamna 255, intai mascheaza primi 8 biti din stanga(ii seteaza la 0) si copiaza ceea ce ramane adica ceilalti 8 biti care reprezinta prima parte a short-ului.

Dupa care muta primi 8 biti din stanga, 8 biti mai la dreapta, si mascheaza biti ramasi in loc.

Codul de mai jos ar trebui sa iti explice destul de clar exact ce se intampla.


char asdf[3];
unsigned short s_int = 800;
bitset<16> x_s_int(s_int);
asdf[0] = s_int & 0xff; // preia primul byte prin mascarea celorlalti biti
asdf[1] = (s_int >> 8) & 0xff;
asdf[2] = '\0';
bitset<16> x_ff(0xff);
cout << asdf << endl;
unsigned short s;
memcpy(&s, asdf, sizeof(unsigned short));
cout << s << endl;

cout << "s_int =\t " << x_s_int << endl;
cout << "0xff =\t " << x_ff << endl;
bitset<16> x_asdf_0(asdf[0]);
bitset<16> x_asdf_1(asdf[1]);
cout << "s_int & 0xff; = " << x_asdf_0 << endl;
cout << "(s_int >> 8) & 0xff;" << x_asdf_1 << endl;

cifer este un std::string.

Pentru a vedea cate bucati am impart marimea la ce am de trimis(in cazul asta in cate caractere sunt/sau cati bytes sunt)

la marimea maxima a unei bucati(255);

si fac calculele necesare.

Mai jos un exemplu


const int BUFF_SIZE = 255; // max size of the chunks
unsigned char chunks = cifer.size() / BUFF_SIZE; // number of chuncks that compose our encrypted message
if((chunks * BUFF_SIZE) > cifer.size()) // checking if it rounded up
{
chunks--;
}
unsigned char lastChunkSize = cifer.size() - (chunks * BUFF_SIZE); // size of the last chunk
mp_sockClient->Write(&chunks, 1); // sending the number of chunks
mp_sockClient->Write(&lastChunkSize, 1); // sending the size of the last chunk
mp_sockClient->Write(cifer.c_str(), cifer.size()); // sending the whole encrypted message

Pentru citire fac ceva de genul asta


unsigned char chunks; // number of 255 bytes chunks will be received
unsigned char lastChunkSize; // size of the last chunk
mp_sockClient->Read(&chunks, 1); // reading number of chuncs from socket
mp_sockClient->Read(&lastChunkSize, 1); // reading size of last chunk from socket

// loop to read every 255 bytes chunk and append it to cifer
for(int i = 0; i < chunks; i++)
{
char buff[255];
mp_sockClient->Read(buff, 255);
cifer.append(buff, 255);
}

char* lastBuff = new char[lastChunkSize];// new buffer with the size of the last chunk
mp_sockClient->Read(lastBuff, lastChunkSize);// readin it
cifer.append(lastBuff, lastChunkSize); // apending it

Pana acum nu m-am complicat insa cu biti, totusi operatiile nu ar trebui sa fie diferite atat timp cat lucrezi cu int-uri mai mici de 255 si folosesti unsigned char;

Link to comment
Share on other sites

Nu trebuie sa-i dai neaparat char chiar daca functia asta cere. Poti sa-i dai orice adresa de memorie si el va trimite ce gaseste acolo byte cu byte pana acopera dimensiunea data.

De ex ca sa trimiti:


int ival = 42;
send(0, (char*)&ival, sizeof(int), 0); //sizeof(int) = 4

si ca sa primesti:


int ival = 42;
recv(0, (char*)&ival, sizeof(int), 0);

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...