I have an assignment for school, and one part is to send a set of ints, chars char* from a client to a server using socket programming. Sending ints or chars works just fine, but is there any way to send the entire struct as one packet? Read about serializing, but I cant seem to make it work. Here's a code snippet:
The struct looks like this:
struct Msg
{
int a;
char b;
char *user;
};
Client:
init variables and such...
int netcom(char* ip, int port) {
sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
// clear the structure
bzero(&serveraddr, sizeof(struct sockaddr_in));
serveraddr.sin_family = AF_INET;
// add the server adress
inet_pton(AF_INET, ip, &serveraddr.sin_addr);
// add the port number
serveraddr.sin_port = htons(port);
// connect
connect (sd,(struct sockaddr*)&serveraddr, sizeof(struct sockaddr_in));
}
int sendPkg(struct Msg msg) {
send(sd, &msg, sizeof(msg), 0);
}
And the part of the server that receives looks like this:
char buf[100];
recv(sd[i], buf, sizeof(buf)-1, 0);
The client sends perfectly fine, and the server receives fine. But I have no idea what I'm sending, and how to read it properly. So that's my question. How to properly send over the data from a struct
using sockets.
Sending a struct directly seems appealing because you can do it in a single call... and worse: sometimes it will actually work out great! It's a trap though.
The first reason this is a trap is that, in your case for example, one of the elements is a pointer. Except in very rare cases, the receiver will get that pointer which is useless on that end -- the pointer points to memory that is valid for the sending process.
The second, and less obvious reason this is a trap is that the layout (in memory) of a structure on one side of a socket might not be identical on the other side. This is a function of machine architectures and compiler settings, making it unsafe to trust that it will "just be ok". This trap is easy to get away with for a while, especially during development, where you're likely to have compatible architectures on each side of your test.
Your best bet is to send each field individually, even though that is painful. You can make it less painful by applying a little object oriented design to your code though, by creating a dedicated sender and receiver function for this structure. These functions have intimate knowledge of the contents and order, and package it into smaller sends (which, in the case of your char *
, probably need to include a length before the string data).
A packaged send as I described is fine as long as the structure hasn't changed from one side of the socket to the other, but you might want to be wary of having a different version of the structure on one end... say a new (or not present) field. To handle this, you could consider tagging the data you send (rather than assuming "first we send a
, then b
, etc.").
It would be beneficial to look into the many JSON libraries to manage your serialization. This gives you an easy to read format that addresses all of the issues I've presented here, and there are JSON libraries available for nearly every common programming language.