Parsing and data types problem...

Posted on 2003-10-21
Last Modified: 2010-04-15
...won't this hell ever end?

Is there any to "build" a UDP packet that can contain ints and chars? recvfrom() won't mind what kind of data it receives, that's up to the parsing, so can I create an array that will contain both these types? And this brings me another question; I'm parsing the received packets in the server side like this:

strncpy(oneInt,buffer,4); /*i copied a (char)int */
strncpy(string,&buffer[4],64); /*copied a 64B string*/

But how can I know if a char casted int will really take up 4B? Nevertheless, I need to send the array containing that int, so how can I retrieve it from the array later? I know I have to get 4B but how do I specify that in terms of positioning? Like this: myvar=buffer[68]; ??? I don't think this is right! :((
Question by:bass20
  • 3
  • 2
  • 2
  • +3
LVL 23

Expert Comment

ID: 9592393
First, you cannot use functions (like strncpy) that treat the buffer as a NUL-teminated
ASCII string.  If your integer is a very small value (like 1), 3 of its four bytes will be 0,
which will be interpreted as "end of string" for all the string handling functions.  

If you want to store a 4 byte integer into the buffer you will have to use a cast like this:

oneInt = *(int *)buffer;

which means "force buffer to be a pointer to an integer (rather than a pointer to char),
then set oneInt to the value of the integer pointed to."


myvar = *(int *)(buffer+68);

which means "force the address of the 68th byte of buffer to be interpreted as a pointer
to an integer, then set to the value of the integer pointed to."

LVL 45

Expert Comment

ID: 9592412

A packet will "send" anything that you put into it.  It's up to your client and server to be in agreement on the contents of the data.

This is why data to/from public servers is usually in ASCII (or UNICODE or some other portable mechanism).  "65536" is always "65536" when sent as a string of characters and the receiver is responsible for interrogating it.  Sending 65536 as a binary value can result in the receiver accessing the value is if it were 0, 1, 65536, or other values.


Expert Comment

ID: 9592506
Try putting all data types you want to send in VARIANT type array and send that array instead.

for example, to send one integer and one character then you have to do the following:

     int nIntegerToSend = 1;
     char cCharToSend = 'a';

     VARIANT vArray[2];

     vArray[0].vt = VT_I4;
     vArray[0].lVal = (long)nIntegerToSend;

     vArray[0].vt = VT_UI1;
     vArray[0].bVal = (unsigned char)cCharToSend;

Now you have to send the buffer pointer to by vArray (length = sizeof(vArray)).

When you receive the buffer you will need to do something like this:

     int nBufferLength = /* Length of buffer received from socket (this has to be multible sizeof(VARIANT) */
     void *pBuffer = /*Start of Buffer received from socket*/

     void *pStart = pBuffer;
     VARIANT vt;
     while(1 == 1)
          memcpy(&vt, pBuffer, sizoef(VARIANT));
             case VT_I4:
                int nIntegerReceived = (int)vt.lVal;
             case VT_UI1:
                char cCharReceived = (char)vt.bVal;
              /* Handle other datatypes */
          /* Loop until you reach the end of buffer received */
         pBuffer += sizoef(VARIANT); /* make sure to handle buffer length not to get beyond the received buffer length :-) */
         if(pStart + nBufferLength <= pBuffer)


Expert Comment

ID: 9593854
Watch out for the int casting. If you're doing something like

char buffer[SIZE];
recvfrom(s, buffer, SIZE, ...);

You cannot safely cast a byte pointer to an int pointer. Some cpus aren't as forgiving wrt unaligned memory accesses as the x86.

As for the size of an int, you don't know whether its really four bytes or something else. Use some fixed-width type such as 'uint32_t' instead.

You'll also have to cater for byte-ordering differences between cpus by using a predetermined byte order when sending data over a network. Network byte order is big-endian.

Furthermore, it's probably a good idea to use some defensive programming when receiving UDP packets over a network. Imagine what would happen if someone sends you a malformed packet.

To avoid these headaches, better use a text encoding (as Kdo suggested). This is much less error-prone and easier to write.


Author Comment

ID: 9594248
So there isn't a way to use a type like void, wich will hold any kind of data? For ex:

void buffer[10];


I've posted a similar question before; I just can't quite figure out how to "blend" the two different types inside one array to use with sendto(). Should I convert all types to char?
VMware Disaster Recovery and Data Protection

In this expert guide, you’ll learn about the components of a Modern Data Center. You will use cases for the value-added capabilities of Veeam®, including combining backup and replication for VMware disaster recovery and using replication for data center migration.


Accepted Solution

mtmike earned 50 total points
ID: 9594473
The variant approach:

struct variant {
  char type;
  union {
    char c;
    short s;
    int i;
    long l;
    float f;
    double d;

Still has the same size/byte-order problems (not too mention overhead).

Maybe explicit encoding/decoding is a better idea:

typedef unsigned char uint8_t;

void uint_encode(uint8_t *buffer, unsigned int data)
      buffer[0] = (data >> 24) & 0xff;
      buffer[1] = (data >> 16) & 0xff;
      buffer[2] = (data >> 8) & 0xff;
      buffer[3] = data & 0xff;

unsigned int uint_decode(const uint8_t *buffer)
      int data;

      data = (unsigned int) buffer[0];
      data = (data << 8) | (unsigned int) buffer[1];
      data = (data << 8) | (unsigned int) buffer[2];
      data = (data << 8) | (unsigned int) buffer[3];
      return data;

Caters for size, byte-order and alignment problems.
LVL 22

Expert Comment

ID: 9595637
The simplest way to interpret an incoming buffer of bytes as a struct is to just overlay the buffer with a struct pointer.

Something like:

char Buffer[1000];  // the incoming raw net data

typedef struct { int FirstField; double SecondField } TheNetPacket;  // how we want to look at the data

typedef  TheNetPacket *  TheNetPacketPtrType;

TheNetPacketPtrType   TP;

recv( Buffer );

TP = (TheNetPacketPtrType) Buffer;   // have TP point to the incoming data

printf("Received integrer '%d' and double '%f' \n", TP->FirstField, TP->SecondField );

But watch out, as others have noted, this will only work between compatible computers.
If it has to work between any two computers, they have to put the data into some mutually agreed format.

LVL 45

Expert Comment

ID: 9599398
> So there isn't a way to use a type like void, wich will hold any kind of data? For ex:

> void buffer[10];

> strncopy(buffer,"hello",5);
> buffer[5]=123;

Yes, you can do something very similar to this.  But you must be very careful that the receiver knows the format well enough to decode the data.  Look what happens with slightly different data values:

main ()
  unsigned char Buffer[10];

  strcpy (Buffer, "hello");
  Buffer[5] = 44;
  Buffer[6] = 0;

  puts (Buffer);


Note that the decimal value of 44 becomes the period.  If the receiving field is expecting exactly 5 ascii characters and then an 8-bit value, no problem.  But if the text is "free form" as I've inferred, the receiver will have a monsterous time decoding the data.

> I've posted a similar question before; I just can't quite figure out how to "blend" the two different types inside one array to use with sendto(). Should I convert all types to char?

The variant approach that mtmike suggested will solve a lot of this.  Fixed length (fixed position) fields that can be described with struct{} will, too.  So will sending everything in ASCII (unicode).

Implementing variants is pretty easy.  For a first cut I would limit the data types to native types shown in mtmike's example.  Each item will be sizeof (variant) bytes long, but that's ok for starters.  Once the basics are in place for you to send/receive data you can then pack the data and include a string type.


Author Comment

ID: 9606088
The recipient of the packet always knows the format in order to parse it; here's how I'm doing it now, I'm about to start testing it:

char buffer[20];
int hey=3;

memcpy(buffer,(char *)hey,4);


Comments, please?
LVL 45

Expert Comment

ID: 9606339

That should be fine.


Featured Post

Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
This tutorial is posted by Aaron Wojnowski, administrator at  To view more iPhone tutorials, visit This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.

943 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

4 Experts available now in Live!

Get 1:1 Help Now