English 中文(简体)
Sending struct over TCP (C-programming)
原标题:

I have a client and server program where I want to send an entire struct from the client and then output the struct member "ID" on the server.

I have done all the connecting etc and already managed to send a string through:

send(socket, string, string_size, 0);

So, is it possible to send a struct instead of a string through send()? Can I just replace my buffer on the server to be an empty struct of the same type and go?

最佳回答

Welll... sending structs through the network is kinda hard if you are doing it properly.

Carl is right - you can send a struct through a network by saying:

send(socket, (char*)my_struct, sizeof(my_struct), 0);

But here s the thing:

  • sizeof(my_struct) might change between the client and server. Compilers often do some amount of padding and alignment, so unless you define alignment explicitly (maybe using a #pragma pack()), that size may be different.
  • The other problem tends to be byte-order. Some machines are big-endian and others are little-endian, so the arrangement of the bytes might be different. In reality, unless your server or client is running on non-Intel hardware (which is probably not the case) then this problem exists more in theory than in practice.

So the solution people often propose is to have a routine that serializes the struct. That is, it sends the struct one data member at a time, ensuring that the client and server only send() and recv() the exact specified number of bytes that you code into your program.

问题回答

Are the client and server machines "the same"? What you are proposing will only work if the the C compilers at each end lay out the structure in memory exactly the same. There are lots of reasons why this may not be the case. For example the client and server macines might have different architectures, then the way they represent numbers in memory (big-endian, little-endian) might differ. Even if the clients machines and server machine have the same architecture two different C compilers may have different policies for how they lay out structs in memory (eg. padding between fields to align ints on word boundaries). Even the same conmpiler with different flags might give different results.

Pragmatically, I m guessing that your client and server are the same kind of machine and so what you are proposing will work, however you need to be aware that as a general rule it won t and that s why standards such as CORBA were invented, or why folks use some general representation such as XML.

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].

You can, but you need to be aware of 2 important things.

  1. The programs on both ends have to be ABI compatible. They usually are if both ends run on the same processor architecture, same OS, compiled with the same compiler and compiler flags.
  2. TCP is a stream. You have to make sure you are sending the whole struct. Look at the documentation for the send() call - it returns the nr of bytes sent - which might be less than you told it to. Same on the receiver side. Just because you sent the struct with 1 send call, does not mean you will receive it with 1 recv call. It make take several recv call to get all the pieces.

Yep, structs of the same type are all of the same size. If you get your pointer casting right you re good to go.

In general, it s a bad idea to do this, even if your client and your server turn out to lay out the structure in memory the same way.

Even if you don t intend to pass more complex data structures (that would involve pointers) back and forth, I recommend that you serialize your data before you send it over the network.





相关问题
Fastest method for running a binary search on a file in C?

For example, let s say I want to find a particular word or number in a file. The contents are in sorted order (obviously). Since I want to run a binary search on the file, it seems like a real waste ...

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

Tips for debugging a made-for-linux application on windows?

I m trying to find the source of a bug I have found in an open-source application. I have managed to get a build up and running on my Windows machine, but I m having trouble finding the spot in the ...

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

Encoding, decoding an integer to a char array

Please note that this is not homework and i did search before starting this new thread. I got Store an int in a char array? I was looking for an answer but didn t get any satisfactory answer in the ...

热门标签