0

I am writing a single threaded blocking tcp client on Linux that just sends requests to existing well tested server and waits for the response from it. Server and client are compiled with different compilers. My client code looks like below :-

char buf[sizeof(MyMsg) + sizeof(MySignon) + 10]={0};
MyMsg *msg = reinterpret_cast<MyMsg*>(buf);
MySignon *signOn = reinterpret_cast<MySignon*>(msg->mstrt); //mstrt is double type

msg->type= SIGNON;
msg->subtype= USER_SIGNON;
strncpy(signOn->szUserId, user, sizeof(signOn->szUserId)-1);
signOn->iApplicationMode =  SM_SIGN_ALLOC;
SetMsgLen(msg, sizeof(MySignon));

auto ret = send(fd, reinterpret_cast<char*>(msg), msg->msglen);

and send looks like below :-

Status Send(int fd, char* data, size_t length)
{
    size_t written = 0;
    errno=0;
    do{
         MyMsg* pm = reinterpret_cast<MyMsg*>(data+written);
         int r = ::write(fd, pm, length-written);

         if (errno == 0)
             written+=r;

     } while (length > written and errno == 0);
}

The Problem :- When I run this, server receives a very large size from msg->msglen. There is another client which does exactly same steps and which is compiled with same compiler as server that works fine. That is why I suspect different compilers might be treating structures in different way (may be due to struct padding). What is wrong here. What is work around for this problem.

Anand Shah
  • 133
  • 10
  • 2
    Compilers are allowed to pad structures as they see fit; there is no standardized in-memory layout for C++ objects. That's why it's important to do proper serialization when sending and receiving data across the network, if you want any kind of portability. See: https://stackoverflow.com/questions/44815764/how-does-one-properly-deserialize-a-byte-array-back-into-an-object-in-c/44816991#44816991 – Jeremy Friesner Mar 08 '21 at 16:36
  • 1
    Strange struct packing is why you should use `static_assert` with sizeof and offsetof to guarantee that structs are the correct size and members are in correct locations. Either that or make or find some kind of Decoder object which takes a reference or pointer to a buffer and maintains a pointer while providing functions like `get_uint32le` – Zan Lynx Mar 08 '21 at 16:38
  • 2
    The very first thing you should do is dump your received message buffer as hexadecimal in a debugger or make your own print statement. I suspect you either did not get the data you expected, or it is in a different format such as big-endian. – Zan Lynx Mar 08 '21 at 16:40
  • And of course, your code as written here would never work at all. Why not post the actual program or at least a link to it. – Zan Lynx Mar 08 '21 at 16:41

0 Answers0