You can, if the client and the server have laid out the struct exactly the same way, meaning that the fields are all the same size, with the same padding. For instance if you have a long
in your struct, that might be 32bits on one machine and 64bits on the other, in which case the struct will not be received correctly.
In your case, if the client and the server are always going to be on very similar C implementations (for instance if this is just code you're using to learn some basic concepts, or if for some other reason you know your code will only ever have to run on your current version of OSX), then you can probably get away with it. Just remember that your code will not necessarily work properly on other platforms, and that there's more work to do before it's suitable for use in most real-world situations.
For most client-server applications, this means that the answer is you can't do it in general. What you actually do is define the message in terms of the number of bytes sent, what order, what they mean, and so on. Then at each end, you do something platform-specific to ensure that the struct you're using has exactly the required layout. Even so, you might have to do some byte-swapping if you're sending integer members of the struct little-endian, and then you want your code to run on a big-endian machine. Data interchange formats like XML, json and Google's protocol buffers exist so that you don't have to do this fiddly stuff.
[Edit: also remember of course that some struct members can never be sent over the wire. For instance if your struct has a pointer in it, then the address refers to memory on the sending machine, and is useless on the receiving end. Apologies if this is already obvious to you, but it certainly isn't obvious to everyone when they're just beginning with C].