Thread: sending structures through sockets

  1. #1
    Registered User
    Join Date
    Jun 2008
    Posts
    11

    sending structures through sockets

    Hello,

    I was just wondering if there was any way to safely send structures across a network in sockets, since the send( function can possibly the entire data buffer I give it.

    If I used
    Code:
    send(mysock, (char*)mystruct, sizeof(mystruct), 0)
    for example, and send didn't send the entire structure, what would I do next?

  2. #2
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Code:
    send(mysock, (char*)mystruct, sizeof(mystruct), 0)
    You face several issues if you send a structure that way. Compilers can add padding between members of a structure, and for this to work, that padding must be the same on both machines. Also, the "endianness" of the machines must match - if you send a structure from a little endian machine to a big endian one that way, the result will be garbage. Also, any pointers in the structure are meaningless when they reach the other side.

    If you want portability, allocate a character array long enough to hold the data, serialize the data to that array, and then send the array with send(). Unfortunately, that word 'serialize' involves 90% of the work in that. By serialize, I mean to write the data in a known and defined way. How you do this is up to you, unless you need to follow some already established protocol. See this URL
    I'm assuming you can invent whatever network protocol you want. Example, take this struct:
    Code:
    struct
    {
       char some_string[30];
       uint32_t some_int;
    };
    I could send it by just creating a string, and doing:
    Code:
    char buffer[50];
    sprintf(buffer, "%s\t%u\n", some_string, some_int);
    send(buffer ...);
    ...making sure that some_string never contained a '\t', lest my communications become garbled. I now have a sort of text based protocol, whereby I can send a string and an integer. (If you want to send other things, you just have to send enough data so that the other side knows what it is looking at/it can differentiate between different 'messages')
    If text is too cumbersome, you can save some space by sending binary integers. I could have sent the byte stream:
    Code:
    48 65 6C 6C 6F 00 00 00 05 39
    Which is the string "Hello", a nul terminator, and the number 1337 encoded as a big endian 32 bit unsigned integer.

    To convert to big endian/back to the endianness of your computer, you can use the htonl, htons, ntohl, ntohs() functions.

    Overall, I could probably fill a tutorial on serialization alone. Understanding of what endianness is (see above url) and serialization are topics any programmer should be aware of.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

  3. #3
    Registered User
    Join Date
    Jun 2008
    Posts
    11
    Thank you Cactus_Hugger!
    I'm somewhat new to writing programs, so I didn't think about portability.
    I'll be sure to read the serialization FAQ.

  4. #4
    Registered User
    Join Date
    Jun 2008
    Posts
    11
    So, after I serialize the data, would this be a good way to send it?
    Code:
    int SockSend(SOCKET *theirsock, char* buf, int len)
    {
    	int nError;
    	int nsent = 0;
    
    	do
    	{
    		nError = send(&theirsock, &buf[nsent], len - nsent, 0);
    		if(nError == SOCKET_ERROR)
    		{
    			printf("SockSend: send( failed: %d\n", WSAGetLastError());
    			closesocket(*theirsock);
    			WSACleanup();
    			return 0;
    		}
    		nsent += nError;
    	} while(nsent != len);
    
    	return nsent;
    }

  5. #5
    int x = *((int *) NULL); Cactus_Hugger's Avatar
    Join Date
    Jul 2003
    Location
    Banks of the River Styx
    Posts
    902
    Yup, that will work, assuming your sockets are blocking. (this is the default, so unless you change them, they are.)

    The only thing I'd change is the nError == SOCKET_ERROR (I would've used nError < 0) to keep at least that much portable. (AFAIK, SOCKET_ERROR is a windows only thing) But you've already got WSA* stuff, so if you're not concerned about portability, this point is moot.
    long time; /* know C? */
    Unprecedented performance: Nothing ever ran this slow before.
    Any sufficiently advanced bug is indistinguishable from a feature.
    Real Programmers confuse Halloween and Christmas, because dec 25 == oct 31.
    The best way to accelerate an IBM is at 9.8 m/s/s.
    recursion (re - cur' - zhun) n. 1. (see recursion)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Sending Hex to sockets?
    By chrisjmoss in forum Networking/Device Communication
    Replies: 1
    Last Post: 04-03-2008, 05:50 AM
  2. Sending structures through the network
    By Mortissus in forum C Programming
    Replies: 3
    Last Post: 07-26-2007, 10:24 AM
  3. Simple sockets - sending error
    By More_Coffee in forum Networking/Device Communication
    Replies: 4
    Last Post: 04-15-2007, 04:41 AM
  4. Sockets... Sending Binary Data. Please help
    By avalanche333 in forum C++ Programming
    Replies: 16
    Last Post: 03-31-2007, 12:56 PM
  5. Replies: 1
    Last Post: 08-01-2002, 08:26 PM