Home > Blockchain >  is it possible to convert a char array into structure with data alignement padding?
is it possible to convert a char array into structure with data alignement padding?

Time:02-04

This is my structure :

struct packetHeader {

  uint16_t m_packetFormat;
  uint8_t m_gameMajorVersion;
  uint8_t m_gameMinorVersion;
  uint8_t m_packetVersion;
  uint8_t m_packetId;
  uint64_t m_sessionUID;
  float m_sessionTime;
  uint32_t m_frameIdentifier;
  uint8_t m_playerCarIndex;
  uint8_t m_secondaryPlayerCarIndex;

};

There is padding for data alignement, so if I use std::memmove the padding value is changed, and mess up my structure.

I do not want to use __attribute__((packed))

Is it possible ? I could create a function for add padding in the char array, but it's dirty...

Thank you !

EDIT : Exemple below

  sockaddr_in gameAddress; //Ici sera stocké les informations de connexion du jeu (ip..)
  socklen_t gameAddressSize = sizeof gameAddress;

  addrinfo hints, *res, *p; //Ces structures de données contiendront les informations de connexion de l'application
  int appSocket; //Ici, la socket qui servira à enclencher la connexion
  int byte_count;

  timeval socketTimeout;

  int sockErr; //gestion erreur

  packetHeader header;
  memset(&header, 0, sizeof header);

  //Paramétrage de la socket
  memset(&hints, 0, sizeof hints); //Remise à zéro de hints
  hints.ai_family = AF_INET; //IPv4
  hints.ai_socktype = SOCK_DGRAM; //UDP type
  hints.ai_flags = AI_PASSIVE; //L'adresse IP de la machine obtenu automatiquement

  sockErr = getaddrinfo(NULL, PORT, &hints, &res);
  if (sockErr == 0) {
    std::cout << "Paramétrage de l'adresse ok !" << '\n';
  } else {
    perror("Erreur du paramétrage de l'adresse  ");
  exit(1);
  }

  appSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); //Initialisation de la SOCKET
  if (appSocket != INVALID_SOCKET) {
    std::cout << "Socket valide" << '\n';
  } else {
    perror("Erreur de la socket  ");
    exit(1);
  }

  //Ici, l'on va ignorer l'erreur "address already in use"
  int yes = 1;
  setsockopt(appSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof yes);

  //Ici, nous allons définir le timeout de 5sec
  socketTimeout.tv_sec = 5;
  socketTimeout.tv_usec = 5000;
  setsockopt(appSocket, SOL_SOCKET, SO_RCVTIMEO, &socketTimeout, sizeof socketTimeout);

  //Activation du mode "Écoute"
  sockErr = bind(appSocket, res->ai_addr, res->ai_addrlen); //Connexion de la socket au bon PORT
  if (sockErr != INVALID_SOCKET) {
    std::cout << "Bind valide" << '\n';
  } else {
    perror("Erreur du bind ");
    exit(1);
  }

  while (true) {
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    byte_count = recvfrom(appSocket, &header, sizeof header, 0, (sockaddr*)&gameAddress, &gameAddressSize);

The m_sessionUID must always be the same for each packet, but it's not the case...

CodePudding user response:

I think I will use #pragma, it seem to be the best solution. I thought not use it because it's not recommended, but in my case, I'm not sure there is another alternative. Thank you everyone :)

CodePudding user response:

As you use UDP, you will have to read the packet at once. But you can read it in a char array and then unserialize that array into your struct:

  while (true) {
    char buffer[sizeof(header)];
    const char *p = buffer;
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    byte_count = recvfrom(appSocket, buffer, sizeof header, 0, (sockaddr*)&gameAddress, &gameAddressSize);
    // test for byte count ommited...
    memcpy(&header.m_packetFormat, p, sizeof(header.m_packetFormat));
    p  = sizeof(header.m_packetFormat);
    memcpy(&header.m_gameMajorVersion, p, sizeof(header.m_gameMajorVersion));
    p  = sizeof(header.m_gameMajorVersion);
    memcpy(&header.m_gameMinorVersion, p, sizeof(header.m_gameMinorVersion));
    p  = sizeof(header.m_gameMinorVersion);
    ...
  •  Tags:  
  • Related