0

How do i copy a struct across a network socket? I want to exchange the following kind of struct over a socket:

struct msg{
  char *from;
  char *to;
  int size;
};
struct msg m1={"me","you",20};

int sd=socket(AF_INET,SOCK_STREAM,0);
send(sd,&m1,sizeof(struct msg),0);

However i'm unable to make sense of the values received on the other side. Tried changing the struct fields from pointers to fixed size arrays but that doesn't help either.

user3818219
  • 43
  • 1
  • 4
  • You're copying the struct itself just fine. Unfortunately, though, those pointers will be worse than useless on the other end of the connection. – cHao Jul 30 '14 at 05:33
  • 1
    Those definitely need to be arrays. – T.C. Jul 30 '14 at 05:33
  • Post some array based read and write code as better place to start. – Keith Jul 30 '14 at 05:33
  • you send `sizeof(char *)+sizeof(char *)+sizeof(int)` bytes, but you need send `sizeof(int)+strlne(from)+strlen(to)`. – Sheridan Jul 30 '14 at 05:35
  • 3
    Don't. Don't use structs as network protocols. You are introducing at least six dependencies. Use network protocols as network protocols. Define yourself a wire format, in octets, and write yourself a library to send and receive it. Or use an existing protocol e.g. XML, XDR, ... – user207421 Jul 30 '14 at 05:36
  • If I could agree *more* with @EJP, i don't see how. You need to define how your data is sent. Think about that; then think about it *harder*. You need to develop a delivery *protocol* for how you represent your *complete* data on the wire, delivered to someone that knows how to reverse that protocol and turn it back into something they understand. This kind of work is usually simple, but often very *tedious* and it is very easy to build in mistakes or assumptions. Things like [ASN.1](http://en.wikipedia.org/wiki/Abstract_Syntax_Notation_One) don't exist by accident. – WhozCraig Jul 30 '14 at 05:58
  • [Related question](http://stackoverflow.com/questions/25028553/system-call-to-populate-struct-values). – WhozCraig Jul 30 '14 at 06:02

1 Answers1

1

There are a couple of things wrong with your implementation. What you need to understand is that data on the wire (communication link) is just an array of bytes and it is up to the platforms on both sides of the link to parse them into something more meaningful. This means that serialization of data to the communication media and deserialization of it back to human readable format have to match each other as well as the platform used on each side. For instance sending from a little endian platform to a big endian platform (intel to motorolla) without taking care of byte switching will result in completely messing up the data on the other side.

Coming back to your example, you naively passed the pointer to your struct as if it was an array of characters. This assumes that the memory allocated to your variables is contiguous which is not necessarily the case. In addition, there is the issue of byte alignment for each side's environment which means that unless it is set to 1 on both sides, the compiler on the sending side may pad some of the variables with zero values, causing the other side to read them differently if it is set to a different byte alignment.

So to summarize: In order for this to work safely, you need to copy your variables explicitly to the sending buffer, and read them explicitly on the other side. You also should make sure that you are using the same platform on both sides (I'm assuming you have intel for both). By the way, when dealing with strings, you need to ensure that the trailing 0 is copied so when you try to read the string on the other side, it will read correctly.

o_weisman
  • 804
  • 7
  • 19