LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 10-05-2011, 07:41 AM   #1
Beelz
LQ Newbie
 
Registered: Oct 2011
Distribution: opensuse 10.3
Posts: 5

Rep: Reputation: Disabled
problem receiving UDP packets with C, on openSuse


I am trying to receive an UDP packet from a device. I know the IP-adres of this device and the port number it is sending the packets to. When I use the code below (example linux howtos) and change the ports it doesn't receive anything.

Code:
/* Creates a datagram server.  The port 
   number is passed as an argument.  This
   server runs forever */

#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>
#include <stdio.h>

void error(const char *msg)
{
    perror(msg);
    exit(0);
}

int main(int argc, char *argv[])
{
   int sock, length, n;
   socklen_t fromlen;
   struct sockaddr_in server;
   struct sockaddr_in from;
   char buf[1024];

   if (argc < 2) {
      fprintf(stderr, "ERROR, no port provided\n");
      exit(0);
   }
   
   sock=socket(AF_INET, SOCK_DGRAM, 0);
   if (sock < 0) error("Opening socket");
   length = sizeof(server);
   bzero(&server,length);
   server.sin_family=AF_INET;
   server.sin_addr.s_addr=INADDR_ANY;
   server.sin_port=htons(atoi(argv[1]));
   if (bind(sock,(struct sockaddr *)&server,length)<0) 
       error("binding");
   fromlen = sizeof(struct sockaddr_in);
   while (1) {
       n = recvfrom(sock,buf,1024,0,(struct sockaddr *)&from,&fromlen);
       if (n < 0) error("recvfrom");
       write(1,"Received a datagram: ",21);
       write(1,buf,n);
       n = sendto(sock,"Got your message\n",17,
                  0,(struct sockaddr *)&from,fromlen);
       if (n  < 0) error("sendto");
   }
   return 0;
 }
When I use the example for the client it does receive.
I don't really know how the device sends the packets, I just know to what port and what IP adres it has.

What do I have to change to receive the packets ??

thanks in advance,
Mike.

Last edited by Beelz; 10-05-2011 at 08:12 AM.
 
Click here to see the post LQ members have rated as the most helpful post in this thread.
Old 10-05-2011, 11:24 AM   #2
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by Beelz View Post
I am trying to receive an UDP packet from a device. I know the IP-adres of this device and the port number it is sending the packets to. When I use the code below (example linux howtos) and change the ports it doesn't receive anything.
The code you posted is for a server, hence the reason for the call to bind(). How can you be sure that the device is sending packets to the system where this code is running? You have chosen INADDR_ANY, which means that all network interfaces (e.g. eth0 and lo), will be used to bind to your specified port to your socket.

If the device is sending datagrams to your system's IP address and port, then you should receive them. If the device is sending to some other IP address and/or port, then you won't receive a thing.

Please confirm that the device is configured properly.
 
Old 10-05-2011, 05:51 PM   #3
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
First of all, for a good tutorial with example code that works, start with Beej's Guide to Network Programming. Second, when testing networking code, use netcat (nc) to confirm that the connection actually works, before you try it on your own code. When you've got it to work with netcat, then try it on your own code. netcat can be a working server or client (or both, if that makes sense), and when confronted with the problem of not knowing whether your server code or your client code or your network doesn't work, it helps to remove one or more of the unknowns in the equation. Once you've done that, run your code under a debugger, like gdb, or one of it's GUI versions like ddd.

--- rod.
 
Old 10-06-2011, 02:02 AM   #4
Beelz
LQ Newbie
 
Registered: Oct 2011
Distribution: opensuse 10.3
Posts: 5

Original Poster
Rep: Reputation: Disabled
thanks for the help,


Using netcat and wireshark I found out that the device is sending its datagrams to an internal IP adres of 224.0.23.12 instead of my IP adres (where the request is coming from) 192.168.10.111
I guess I have to find a way to change the reply IP adres of the device, for that I will contact the supplier.

Thanks for the help,
Mike.
 
Old 10-06-2011, 05:37 AM   #5
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by Beelz View Post
thanks for the help,


Using netcat and wireshark I found out that the device is sending its datagrams to an internal IP adres of 224.0.23.12 instead of my IP adres (where the request is coming from) 192.168.10.111
I guess I have to find a way to change the reply IP adres of the device, for that I will contact the supplier.

Thanks for the help,
Mike.
That's a multicast group IP address.

Here's an example of how I would setup a client to send to that IP address:
Code:
int           sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
unsigned char ttl  = 1;  // time to live

setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
When you send data, use sendto() using a sockaddr_in object in which you specify the multicast group IP (e.g. 224.0.23.12), and of course the port number, of where the device is using.

If the device is acting as a client, then you need to set up a server; then something like this is in order:
Code:
const char* MULTICAST_GROUP = "224.0.23.12";

int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

struct ip_mreq mreq;
memset(&mreq, 0, sizeof(mreq));
mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_GROUP);
mreq.imr_interface.s_addr = htonl(INADDR_ANY);

setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

unsigned char enable = 0;

setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &enable, sizeof(enable));

memset(&server, 0, length);
server.sin_family=AF_INET;
server.sin_addr.s_addr=INADDR_ANY;
server.sin_port=htons(atoi(argv[1]));

bind(sock, (struct sockaddr *)&server, length);

// proceed to receive, similar to what you have implemented before...

P.S. The following may be helpful:
Code:
   The following is borrowed (w/o permission!) from:  Antony Courtney (antony@scrg.cs.tcd.ie)

   Notes about Multicasting:

   Multicast Addresses are restricted to the following ranges:

          224.0.0.0 to 239.255.255.255

   although some of these addresses are reserved for multicasting routing information.
   Applications should not use these reserved addresses, which are:

          224.0.0.0 to 224.0.0.255

   Time-to-Live (TTL) for Multicast Packets are by default restricted to the current
   subnet (TTL=1).  Below are the supported multicast TTL thresholds:

          0   restricted to the same host
          1   restricted to the same subnet (default)
         32   restricted to the same site
         64   restricted to the same region
        128   restricted to the same continent
        255   unrestricted

    The TTL can be changed using setsockopt().  For example:

        unsigned char ttl = 32;
        setsockopt(sock.GetSocketDesc(), IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));

Last edited by dwhitney67; 10-06-2011 at 05:42 AM.
 
2 members found this post helpful.
Old 10-07-2011, 03:06 AM   #6
Beelz
LQ Newbie
 
Registered: Oct 2011
Distribution: opensuse 10.3
Posts: 5

Original Poster
Rep: Reputation: Disabled
Thanks for the point in the good direction, it works fine now!

here is the code I used:

Code:
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>
#include <stdio.h>


int main(int argc, char *argv[])
{
   int sock, length, n;
   socklen_t fromlen;
   struct sockaddr_in server;

   char buf[1024];

   if (argc < 2) {
      fprintf(stderr, "ERROR, no port provided\n");
      exit(0);
   }
   
   const char* MULTICAST_GROUP = "224.0.23.12";
   sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
length = sizeof(server);
   struct ip_mreq mreq;
   memset(&mreq,0, sizeof(mreq));
   mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_GROUP);
   mreq.imr_interface.s_addr = htonl(INADDR_ANY);

   setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
   unsigned char enable = 0;
   setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &enable, sizeof(enable));

   memset(&server,0,length);

   server.sin_family=AF_INET;
   server.sin_addr.s_addr=INADDR_ANY;
   server.sin_port=htons(atoi(argv[1]));


    bind(sock, (struct sockaddr *)&server, length);
   

   while (1) {
       n = recvfrom(sock,buf,sizeof(buf),0,(struct sockaddr *)&server,&length);
       if (n < 0) error("recvfrom");

       write(1,"Received a datagram: ",21);
       write(1, buf, n);
   }
   return 0;
 }
thanks a lot,
mike

Last edited by Beelz; 10-07-2011 at 06:46 AM. Reason: code edit
 
Old 10-07-2011, 06:43 AM   #7
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
I think you are confusing the matter, and I know I'm confused from what you have stated.

You said you had a device on your local subnet that is issuing message(s), and that you have verified this via wireshark. You even went as far as to indicate that the device is using a multicast IP address. You stated that you know the port that this device is sending to as well.

If your device is acting as the server, then all you need to do is develop a client that communicates on the multicast IP address and port. The server will respond to the client via the client's IP address/port.

A simple client, in C++:
Code:
...
  const unsigned short SERVER_PORT     = 12345;
  const char*          MULTICAST_GROUP = "225.0.0.35";

  try
  {
    UDPSocket sock;

    unsigned char ttl = 0;
    setsockopt(sock.getSocketDesc(), IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));

    string query = "Is anyone there?";

    for (;;)
    {
      sock.send(query.c_str(), query.size(), MULTICAST_GROUP, SERVER_PORT);
      sleep(2);
    }
  }
...
A simple server, in C++:
Code:
...
  const unsigned short SERVER_PORT     = 12345;
  const char*          MULTICAST_GROUP = "225.0.0.35";

  try
  {
    UDPSocket sock;

    struct ip_mreq mreq;
    memset(&mreq, 0, sizeof(mreq));
    mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_GROUP);
    mreq.imr_interface.s_addr = htonl(INADDR_ANY);

    setsockopt(sock.getSocketDesc(), IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));

    unsigned char enable = 0;
    setsockopt(sock.getSocketDesc(), IPPROTO_IP, IP_MULTICAST_LOOP, &enable, sizeof(enable));

    /*
    unsigned char ttl = 0;
    setsockopt(sock.getSocketDesc(), IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
    */

    sock.enableReusePort();
    sock.bind(SERVER_PORT);

    for (;;)
    {
       string         clientAddr;
       unsigned short clientPort;
       char           rcvdMsg[1024];

       int bytes = sock.recv(rcvdMsg, sizeof(rcvdMsg) - 1, clientAddr, clientPort);

       if (bytes > 0)
       {
          rcvdMsg[bytes] = '\0';

          cout << "Received...\n"
               << "msg : " << rcvdMsg    << "\n"
               << "src : " << clientAddr << "\n"
               << "port: " << clientPort << endl;
       }
    }
  }
...
If your device is pumping out messages on the multicast IP, then I would suggest that you attempt to collect those messages using a client application.

Last edited by dwhitney67; 10-07-2011 at 06:44 AM.
 
1 members found this post helpful.
Old 10-07-2011, 06:50 AM   #8
Beelz
LQ Newbie
 
Registered: Oct 2011
Distribution: opensuse 10.3
Posts: 5

Original Poster
Rep: Reputation: Disabled
I solved it!

Thanks for all your help!
mike
 
Old 10-07-2011, 08:56 AM   #9
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by Beelz View Post
I solved it!

Thanks for all your help!
mike
For the benefit of others, could you please post how you resolved the issue?
 
Old 10-07-2011, 09:09 AM   #10
Beelz
LQ Newbie
 
Registered: Oct 2011
Distribution: opensuse 10.3
Posts: 5

Original Poster
Rep: Reputation: Disabled
sure, I used this server code:

Code:
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <netdb.h>
#include <stdio.h>


int main(int argc, char *argv[])
{
   int sock, length, n;
   socklen_t fromlen;
   struct sockaddr_in server;

   char buf[1024];

   if (argc < 2) {
      fprintf(stderr, "ERROR, no port provided\n");
      exit(0);
   }
   
   const char* MULTICAST_GROUP = "224.0.23.12";
   sock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
length = sizeof(server);
   struct ip_mreq mreq;
   memset(&mreq,0, sizeof(mreq));
   mreq.imr_multiaddr.s_addr = inet_addr(MULTICAST_GROUP);
   mreq.imr_interface.s_addr = htonl(INADDR_ANY);

   setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
   unsigned char enable = 0;
   setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &enable, sizeof(enable));

   memset(&server,0,length);

   server.sin_family=AF_INET;
   server.sin_addr.s_addr=INADDR_ANY;
   server.sin_port=htons(atoi(argv[1]));


    bind(sock, (struct sockaddr *)&server, length);
   

   while (1) {
       n = recvfrom(sock,buf,sizeof(buf),0,(struct sockaddr *)&server,&length);
       if (n < 0) error("recvfrom");

       write(1,"Received a datagram: ",21);
       write(1, buf, n);
   }
   return 0;
 }
I used a client to test if the code worked, an example client is given by dwhitney67 above this post.
If the code is correct you will see the datagrams printed in the konsole.

If you use a client and server on the same computer it will work fine,
For my device to work (connected to network) I had to turn off the firewall.
 
  


Reply

Tags
receive, socket, udp


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Sending/receiving UDP packets through a PF_PACKET socket mibo Programming 21 12-06-2011 03:14 AM
[SOLVED] receiving UDP packets - where does the latency come from? mibo Programming 5 06-22-2011 10:33 AM
[SOLVED] Receiving UDP packets avishorp Linux - Networking 3 04-16-2010 05:56 AM
problem in receiving data in udp sockets ramya_ts Linux - Embedded & Single-board computer 1 01-07-2009 02:12 PM
Only receiving UDP packets, no TCP erevlehdeux Linux - Networking 1 04-23-2004 07:36 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 09:14 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration