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);
...
