#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2003
    Posts
    79
    Rep Power
    12

    UDP data convert from string to float or int?


    I am currently working on a networking project and I am having trouble and I cant seam to find an answer.

    First I send a udp packet from the client to the server:

    Code:
    sendto(sock,data,MAXDATASIZE,0,(struct sockaddr *)&server,sizeof(struct sockaddr));
    Say that "data" is a variable containing a string.

    Now the server recieves the udp packet:


    Code:
    recvfrom(sock, buf, MAXDATASIZE, 0, (struct sockaddr *) &remote_addr, &iRemoteAddrLen);
    the variable "buf" holds the string recieved in the packet.

    Now say buf = "0.1f,0.1f,0.2f" (A set of float coordinates in Opengl)

    How can I take the string in "buf" and put the three seprate floats into three variables as floats. Like this:

    Original string in "buf":

    buf = "0.1f,0.1f,0.2f"

    into,

    Three seperate opengl floats:

    x=0.1f
    y=0.1f
    z=0.2f

    Make sense?

    If any one has any ideas or suggestion on how to do this it would be a huge help.

    Thanks
  2. #2
  3. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,607
    Rep Power
    4247
    Use sscanf() to separate the strings into 3 floats. In your case, the code would go something like this:
    Code:
    #include <stdio.h>
    ...
    ...
      char *foo="0.1f,0.2f,0.3f";
      float a, b, c;
    
      sscanf(foo, "%f%*c%*c%f%*c%*c%f", &a, &b, &c);
      printf("%f %f %f\n", a, b, c);
    Hope this helps :)
  4. #3
  5. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    It's actually very easy to do. Just parse that string like you would if you had read it from a disk file or a user typing it in.

    A lot of people here seem to like sscanf(). I never use it because in our C class nobody could get it to work right, so I've shied away from it ever since. I'll take a stab at it and let somebody else tell you what's wrong with it:
    Code:
    // DISREGARD
    fields_converted = sscanf(buf,"%f,%f,%f",&x,&y,&z);
    // DISREGARD
    EDIT:
    Please disregard my attempt at sscanf. I ran a test program and it only converts the first field. Scorpion's example does work. If you are not familiar with sscanf, then you might want to ask him how his format string works. I'm going through the scanf man page now to figure it out for myself.

    EDIT2:
    My sscanf problem was due to the trailing f's. This one does work:
    Code:
    fields_converted = sscanf(buf,"%ff,%ff,%ff",&x,&y,&z);
    Like I've said here before, I'm learning a lot on this forum.


    In our embedded project here at work, we use strtok a lot. Here's how I would do it:
    Code:
    #include <stdlib.h>  // for definition of NULL and for atof()
    #include <string.h> // for strtok
    
    char *sp;
    
    sp = strtok(buf,",");
    if (sp != NULL)
    {
        x = atof(sp);
        sp = strtok(NULL,",");
        if (sp != NULL)
        {
            y = atof(sp);
            sp = strtok(NULL,",");
            if (sp != NULL)
                z = atof(sp);
        }
    }
    BTW, I recently learned that if you send binary data, then you are subject to differences in byte order. Plus, if you send a struct across as a block of binary data, then you are subject to system differences in byte alignment and padding. Therefore, if you are going to send binary data, you must define an exact format for the data, including number of bytes per field and the byte order (should be network order anyway). Then you will need to explicitly put each field of your struct into the packet and explicit read it out on the other end.

    Of course, your use of a character string is one way to get around this problem.
    Last edited by dwise1_aol; May 14th, 2003 at 10:47 AM.
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2003
    Posts
    79
    Rep Power
    12
    Thanks Scorpions4ever that code did the trick. I even ran it thru some OpenGL code to check it liked the floats.


    BTW, I recently learned that if you send binary data, then you are subject to differences in byte order. Plus, if you send a struct across as a block of binary data, then you are subject to system differences in byte alignment and padding. Therefore, if you are going to send binary data, you must define an exact format for the data, including number of bytes per field and the byte order (should be network order anyway). Then you will need to explicitly put each field of your struct into the packet and explicit read it out on the other end.

    Of course, your use of a character string is one way to get around this problem.
    lol...I didnt realize that there was another way to do it. That was one thing I wasn't able to grasp from the online tutorials on winsock(cant afford the book). How does the recieving socket know what the packet is? like a string or a float? I mean I use this function to send


    Code:
    sendto(sock,data,MAXDATASIZE,0,(struct sockaddr *)&server,sizeof(struct sockaddr));
    Can I say

    Code:
    float data[3] = {0.1f,0.2f,0.3f}
    and then send data as an array and the other side treat it as an array? I thought you had to send stuff as strings....
  8. #5
  9. not a fan of fascism (n00b)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Feb 2003
    Location
    ct
    Posts
    2,756
    Rep Power
    95
    nope you dont have to send strings, u just have to cast whatever you send. you could do:

    struct data{
    int x
    char y
    DWORD m
    float h} message

    sendto(sock,(char *)message,sizeof(message),0,(struct sockaddr *)&server,sizeof(struct sockaddr));
  10. #6
  11. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,145
    Rep Power
    2222
    Originally posted by infamous41md
    nope you dont have to send strings, u just have to cast whatever you send. you could do:

    struct data{
    int x
    char y
    DWORD m
    float h} message

    sendto(sock,(char *)message,sizeof(message),0,(struct sockaddr *)&server,sizeof(struct sockaddr));
    Not quite. That would only work if both ends of the connection are the exact same architecture. If both ends are different architecture (<sarcasm>whenever would that happen on the Internet?</sarcasm>), then three things will very likely bite you hard:
    1. Byte order (what Jon Snader calls "byte sex"). Host order could very well not be the same as network order. That's why you need to set the address struct's port with htons(). You will need to do the same for the binary data. The terms "big-endian" and "little-endian" describe the two possible byte orders.
    2. sizeof(int). The size of the int type is implementation dependent. That means it could be 16 bits or 32 bits or even 64 bits.
    3. Byte alignment. an int will normally be aligned with the data bus, which could be 16, 32, or 64 bits wide. This will affect the alignment of the fields within the struct, such that there could very well be extra bytes of padding between fields. Therefore, the "same" struct on different architectures could be different sizes and fields therein could get misread.

    Case in point of #3: For our first Linux file manipulation program, I started working on it on a Windows 98SE machine, then copied the files over to a Linux box to finish it. That included a data file of structs which I just could not get to work right. Upon examination, I found that the filesize was wrong. I deleted it and recreated it under Linux. This time it worked and the filesize was correct.

    That is why I wrote:
    Therefore, if you are going to send binary data, you must define an exact format for the data, including number of bytes per field and the byte order (should be network order anyway). Then you will need to explicitly put each field of your struct into the packet and explicit read it out on the other end.
    You should find examples of such format definitions in the NTP (Network time Protocol -- RFC 1769) RFCs and others.
    Last edited by dwise1_aol; May 15th, 2003 at 03:14 PM.

IMN logo majestic logo threadwatch logo seochat tools logo