Thread: Issue receiving data from socket (multicast)

  1. #1
    Registered User
    Join Date
    Aug 2010
    Posts
    8

    Issue receiving data from socket (multicast)

    Hi I'm having some kind of problem here that I can't identify ...

    I want to get UDP data that is sent to a multicast address so my guess is to create a socket and bind it to the multicast address and port where the data is sent to . I'm using openSUSE and coding in c++

    I configure the socket

    Code:
        struct sockaddr_in mysocket;
        struct ip_mreq group;
        int sd;
        int dblength;
        char dbuffer[1024];
        int reuse = 1;
    
    try{
    	sd = socket(AF_INET, SOCK_DGRAM, 0);
            setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse));
               
            memset((char *) &mysocket, 0, sizeof(mysocket));
            misocket.sin_family = AF_INET;
            misocket.sin_port = htons((unsigned int)multicastport.c_str());
            misocket.sin_addr.s_addr = htonl(INADDR_ANY); 
        
        bind(sd, (struct sockaddr*)&misocket, sizeof(misocket));
              
        group.imr_multiaddr.s_addr = inet_addr(multicastaddress.c_str());
        group.imr_interface.s_addr = inet_addr("192.168.0.8");
                    setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group));
              }
    And here I try to read from the socket :

    Code:
    int readLength = -1;
            printf("\nReading from socket");
    
            try{
            while((readLength=read(sd, dbuffer, dblength)) >=0){
                //some data processing here when it works
                cout << readLength <<endl;
                printf(dbuffer);
            }
            if(readLength < 0){
                printf("\nError buffer empty\n");
            }
    
            close (sd);
            printf("\nReading .... OK\n");}
            catch(unsigned int a){
                perror("Error reading");
                close(sd);
            }
    I get this output

    Code:
    Reading from socket
    Error buffer empty
    Reading .... OK
    It compiles and executes "ok" and I know for sure (wireshark captures and server's log) that the UDP packets are being sent so I don't know why I'm not receiving... socket not correctly configurated?

    Any idea where am I failing?

    JessH

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Slightly Advanced Techniques
    Are you actually on an IPv6 network?

    > while((readLength=read(sd, dbuffer, dblength))
    What did you initialise dblength to?
    Was it sizeof(dbuffer)-1 perhaps?
    If not, then you probably got it wrong.

    > printf(dbuffer);
    Your box has just been hacked by someone!
    a) NEVER pass a raw string as the format to printf. If there are any % characters, you're in the doo-doo
    b) You don't add a \0 to the received message - that's why there is a -1 in the above comment, so you have room to add one.

    > printf("\nError buffer empty\n");
    You could always print out the value of errno (or use strerror()) and get it to tell you WHY it failed.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    C lover
    Join Date
    Oct 2007
    Location
    Virginia
    Posts
    266
    I thought the call for UDP sockets was recvfrom() and not read().

    EDIT: I think I'm wrong. I actually think read() calls recvfrom(). Someone correct me.
    Last edited by Syscal; 08-30-2010 at 09:19 AM.

  4. #4
    Registered User
    Join Date
    Jul 2010
    Location
    Oklahoma
    Posts
    107
    JessH,

    I checked with W. Richard Stevens UNIX Network Programming: Networking APIs: Sockets and XTI Volume 1 2nd Ed. New Jersey: Prentice Hall 1998. ISBN 0-13-490012-X. The socket options you've set are what concern me. For example, SO_REUSEADDR was mentioned back in the section about TCP sockets about page 194. The Echo Server example on page 214 (the UDP specific material) looks like:

    Code:
    int main(int argc, char **argv)
    {
       int sockfd;
       struct sockaddr_in servaddr, cliaddr;
    
       sockfd = socket( AF_INET, SOCK_DGRAM, 0 );
    
       bzero( &servaddr, sizeof( servaddr ) );
    
       servaddr.sin_family = AF_INET;
       servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
       servaddr.sin_port = htons( SERV_PORT );
    
       bind( sockfd, (SA*) &servaddr, sizeof( servaddr ) );
    
       // uses the socket to do the echo service...
    
       return 0;
    }
    I just copied it from the book, and he used some fancy wrapper functions for handling errno and such. But there really wasn't that much to a UDP socket. I didn't notice you setting the port in your code block, perhaps there's something there. The constant in Stevens' code SERV_PORT was defined in his library as some well known port number (a short integer in fact). You are welcome to tinker with his example.

    Also, we didn't usually use 'read' either, and Stevens actually used recvfrom and sendto in his implementations...maybe something there too. I checked with Paul S. Wang An Introduction to ANSI on UNIX Boston: PWS Publishing 1993. ISBN 0-534-14232-X. Read doesn't pad with the string terminator, it reads up to the number passed as the length parameter. I don't think that's your problem unless the length parameter didn't get set properly (it wasn't in your post).

    Best Regards,

    New Ink -- Henry
    Last edited by new_ink2001; 08-30-2010 at 09:59 AM. Reason: signature block

  5. #5
    Registered User
    Join Date
    Aug 2010
    Posts
    8
    Thank you for your replies
    Quote Originally Posted by Salem View Post
    Slightly Advanced Techniques
    Are you actually on an IPv6 network?

    > while((readLength=read(sd, dbuffer, dblength))
    What did you initialise dblength to?
    Was it sizeof(dbuffer)-1 perhaps?
    If not, then you probably got it wrong.
    True, I got that wrong !!!

    Quote Originally Posted by Salem View Post
    > printf(dbuffer);
    Your box has just been hacked by someone!
    a) NEVER pass a raw string as the format to printf. If there are any % characters, you're in the doo-doo
    b) You don't add a \0 to the received message - that's why there is a -1 in the above comment, so you have room to add one.
    You are right hehe I just wanted to know if there was anything there , the "processing" will go different, and I'll remember about the \0

    Quote Originally Posted by Salem View Post
    > printf("\nError buffer empty\n");
    You could always print out the value of errno (or use strerror()) and get it to tell you WHY it failed.
    The problem was that the buffer was empty, like if no data was read.

    Quote Originally Posted by Syscal View Post
    I thought the call for UDP sockets was recvfrom() and not read().

    EDIT: I think I'm wrong. I actually think read() calls recvfrom(). Someone correct me.
    I thought the same, I even tried with recvfrom, which has not a very "friendly" interface, but it looks like read() can do the job too (not cofirmed though ! )

    Henry, I'll try that code and check the port and the reuse options as you suggested. Also I'll try to post the code again with recvfrom instead of read() and let's see how it goes !


    Edit: I do set the port

    Code:
    misocket.sin_port = htons((unsigned int)multicastport.c_str());
    I tried a couple of things : I used recvfrom, solved dblength issue and deleted the reuse part. Still not working, now it hangs in recvfrom and doesn't continue. ( I also changed the loop a little bit )

    Code:
    fromlen=sizeof addr;
     while((readLength)>=0){
            	printf("\nTrying to read UDP\n");
            ssize_t aux=recvfrom(sd, dbuffer, sizeof dbuffer, 0, (struct sockaddr*)&addr, &fromlen);
    Last edited by JessH; 08-31-2010 at 01:31 AM.

  6. #6
    Registered User
    Join Date
    Jul 2010
    Location
    Oklahoma
    Posts
    107
    JessH,

    I concur that you are giving the port a value, but taking the value returned by 'c_str()' from multicastport (which I believe is a pointer to a c style string) and casting it to an unsigned integer won't likely be the same as using 'atoi' to get the integer value of the string. Thus, recvfrom blocks waiting for input from this arbitrary port number rather than the number contained in the c style string. So the program would seem to hang....

    The member sin_port of mysocket here:

    Code:
    misocket.sin_port = htons((unsigned int)multicastport.c_str());
    Is a short representing the port number. But the value which has been assigned to it is that of the pointer to the string returned by multicastport.c_str(). Is that not true?

    Best Regards,

    New Ink -- Henry

  7. #7
    C lover
    Join Date
    Oct 2007
    Location
    Virginia
    Posts
    266
    Code:
    misocket.sin_port = htons((unsigned int)multicastport.c_str());
    I dont think that would work would it? The argument should be type uint16_t and you pass it a c-string casted. Try:

    Code:
    misocket.sin_port = htons(atoi(multicastport.c_str()));
    You need to #include <stdlib.h>

    EDIT: Darn, New_Ink beat me to it!
    Last edited by Syscal; 08-31-2010 at 05:28 AM.

  8. #8
    Registered User
    Join Date
    Aug 2010
    Posts
    8
    I LOVE YOU ! That was it, I owe you a big one !!! I finished my project !!!! It's working great ! wow I'm so happy !!! A huge thank you !!!!

  9. #9
    C lover
    Join Date
    Oct 2007
    Location
    Virginia
    Posts
    266
    Quote Originally Posted by JessH View Post
    I LOVE YOU ! That was it, I owe you a big one !!! I finished my project !!!! It's working great ! wow I'm so happy !!! A huge thank you !!!!
    Heh, I wish my professors would give projects like this.

  10. #10
    C lover
    Join Date
    Oct 2007
    Location
    Virginia
    Posts
    266
    Quote Originally Posted by new_ink2001 View Post
    JessH,

    I checked with W. Richard Stevens UNIX Network Programming: Networking APIs: Sockets and XTI Volume 1 2nd Ed. New Jersey: Prentice Hall 1998. ISBN 0-13-490012-X. The socket options you've set are what concern me. For example, SO_REUSEADDR was mentioned back in the section about TCP sockets about page 194. The Echo Server example on page 214 (the UDP specific material) looks like:

    Code:
    int main(int argc, char **argv)
    {
       int sockfd;
       struct sockaddr_in servaddr, cliaddr;
    
       sockfd = socket( AF_INET, SOCK_DGRAM, 0 );
    
       bzero( &servaddr, sizeof( servaddr ) );
    
       servaddr.sin_family = AF_INET;
       servaddr.sin_addr.s_addr = htonl( INADDR_ANY );
       servaddr.sin_port = htons( SERV_PORT );
    
       bind( sockfd, (SA*) &servaddr, sizeof( servaddr ) );
    
       // uses the socket to do the echo service...
    
       return 0;
    }
    I just copied it from the book, and he used some fancy wrapper functions for handling errno and such. But there really wasn't that much to a UDP socket. I didn't notice you setting the port in your code block, perhaps there's something there. The constant in Stevens' code SERV_PORT was defined in his library as some well known port number (a short integer in fact). You are welcome to tinker with his example.

    Also, we didn't usually use 'read' either, and Stevens actually used recvfrom and sendto in his implementations...maybe something there too. I checked with Paul S. Wang An Introduction to ANSI on UNIX Boston: PWS Publishing 1993. ISBN 0-534-14232-X. Read doesn't pad with the string terminator, it reads up to the number passed as the length parameter. I don't think that's your problem unless the length parameter didn't get set properly (it wasn't in your post).

    Best Regards,

    New Ink -- Henry
    I have this book and I for some reason, I can't stand those wrapper functions sometimes, I found myself flipping through pages to verify something. I have the first and second editions.

  11. #11
    Registered User
    Join Date
    Jul 2010
    Location
    Oklahoma
    Posts
    107
    Syscal,

    When I was in networking class, it took a minute to get the API down too, so it was a little bit of a pain. It turned into a lesson on the compiler interface when the pthread libraries showed up too. I haven't been able to invest in the second volume of Stevens book yet, I imagine it is a good one.... May I ask to what curriculum it belongs (e.g. MSCS, BSCS,...)?

    But the level of cohesion using those wrappers is much higher (from what I recall in software engineering it's cohesion and the coupling in his library is nearly identical). That is to say, one doesn't have to re-write all of the error handling and debugging information every time one uses the system call function. It's analogous to marrying the error-handling to the system call in one package.

    I've found that a second pair of eyes and some thoughtful reading can be priceless sometimes. I'm starting to think that's the purpose of this board.... You (all) are welcome...it keeps me sharp keeping up with such a great crowd.

    Best Regards,

    New Ink -- Henry

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > misocket.sin_port = htons((unsigned int)multicastport.c_str());
    I'm curious - did you ever get a warning from this?

    I mean, like did you add the cast at any point just to make the compiler STFU?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 48
    Last Post: 09-26-2008, 03:45 AM
  2. Replies: 3
    Last Post: 04-18-2008, 10:06 AM
  3. Replies: 8
    Last Post: 03-10-2008, 11:57 AM
  4. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM
  5. Sockets, multi home, multicast, security, complicated issue
    By ekymk in forum Networking/Device Communication
    Replies: 6
    Last Post: 08-13-2004, 02:12 AM