• C

How do I get ICMP messages back?

I am using a UDP connected socket to send a datagram to a remote host. I want to see if I get ECONNREFUSED or ETIMEDOUT back... How do I do that?

Simple code example would be nice.
RumataAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

emmonsCommented:
After you create the socket, you need to call 'connect' to establish the address to be used in future output to the socket.
If connect comes back < 0, then you check errno for the various connection errors.

.
.
.
sockfd=socket( AF_INET, SOCK_DGRAM, 0);
if( sockfd < 0) /* socket error */
if ( bind( sockfd, . . .) < 0) /* bind error */
if( connect( sockfd, ...) < 0) /* connect error */

 
0
RumataAuthor Commented:
Maybe my question was not clear, but I already did socket, bind and connect calls. Now, I do a send call. It goes through fine (even though the port on remote does not accept anything). Now, I want to know of ECONNREFUSED occured (which it should've because port is not accepting anything). So, my question is how do I know ECONNREFUSED occured...
0
jhanceCommented:
You can't get this error with a UDP connection.  There is no feedback from the socket as to whether what you sent made it through, was lost, was refused, or anything else.  UDP is like a CB radio, you can key the mic and talk all day but you never know if anyone heard you unless they talk back at you.  If you need this kind of information, you need to switch to a TCP connection OR use some type of protocol or handshaking between your sending socket and the receiver to verify that what you sent was received.
0
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

emmonsCommented:
Dang! Got in there too late.
0
emmonsCommented:
Jhance, I am sorry, but you are wrong. All you said is true for UDP sockets that are NOT connected (using the connect call). I am quoting Stevens:

There is another feature provided for connectionless clients that call connect. ... For example, the Internet protocols specify that a host should generate an ICMP prot unreachable message if it recieves a UDP datagram specifying a UDP prot for which no process is waiting to read from. The host that sent the UDP datagram and recives tis ICMP message can try ot identify the process that sent the datagram and notify the process. 4.3BSD for example notifies the process with a "connection refused" error ...

And so on
0
RumataAuthor Commented:
emmons, are you saying that I can do 2 sends, and the second send will return -1 with errno having the error code?
0
RumataAuthor Commented:
emmons, i tried sending two send messages, but none of them return -1. Check it out.


#include "trace.h"
#include <string.h>
#include <errno.h>
#include <sys/signal.h>
#include <fcntl.h>

extern int errno;
int main(int argc, char *argv[])
{
  int n, len;
  int sockfd;
  struct sockaddr_in local_addr, remote_addr;
  char line[30];
  int ttl=1;
  long oldmask;


 

  /* Set the remote host info */
  bzero((char *)&remote_addr, sizeof(remote_addr));
  remote_addr.sin_family = AF_INET;
  remote_addr.sin_addr.s_addr = inet_addr("128.59.35.130");
  remote_addr.sin_port = htons(TRACE_PORT);
 
  /* Open a UDP socket */
  if ((sockfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))<0)
    {
      fprintf(stderr,"Can't open datagram socket!\n");
      sigsetmask(oldmask);
      exit(1);
    }
 
  /* Set the local host info */
  bzero((char *) &local_addr, sizeof(local_addr));
  local_addr.sin_family = AF_INET;
  local_addr.sin_addr.s_addr = htonl(INADDR_ANY);     /* Get the local IP */
  local_addr.sin_port = htons(0);                     /* Get a free port  */
 
  /* Bind the local address */
  if (bind(sockfd, (struct sockaddr *)&local_addr, sizeof(local_addr)) < 0)
    {
      fprintf(stderr,"Can't bind the local address!\n");
      close(sockfd);
      sigsetmask(oldmask);
      exit(1);
    }
  if (connect(sockfd, (struct sockaddr *)&remote_addr, sizeof(remote_addr)) < 0)
    {
      fprintf(stderr,"Can't connect!\n");
      close(sockfd);
      sigsetmask(oldmask);
      exit(1);
    }
  /* Send a stupid datagram */
  strcpy(line, "I am a stupid datagram");
  n=strlen(line);


  if (send(sockfd, line, n, 0) < 0)
    {
      fprintf(stderr,"Can't send!\n");
      close(sockfd);
      sigsetmask(oldmask);
      exit(1);
    }

  if (send(sockfd, line, n, 0) < 0)
    {
      fprintf(stderr,"Can't send!\n");
      close(sockfd);
      sigsetmask(oldmask);
      exit(1);
    }

  fprintf(stderr, "Done!!!\n");
  sigsetmask(oldmask);
  close(sockfd);
}


0
RumataAuthor Commented:
Are you sure that the server does not have something on the UDP port?
I just ran your code here.
I changed one thing, I added a for loop around the second send command, since I was getting a HOST UNREACHABLE error here behind my firewall.
The code returned an error consistanly on the 5th try.
When I set the IP address to be my current machine, I got an error on the second send.
Try putting in the for loop and printing out errno when (if?) you get an error.

for ( i=0; i<50; i++) {
  printf( "Trying for the %d time\n", i);
 if (send(sockfd, line, n, 0) < 0) {
  fprintf(stderr,"Can't send!\n");
  printf( "errno = %d\n", errno);
  close(sockfd);
  sigsetmask(oldmask);
  exit(1);
 }
}


/* with your IP address */
{emmons@home} /home/cemmons/bin/aix4==> ./rumata
Trying for the 5 time
Can't send!
errno = 81

/* with my IP address */
{emmons@home} /home/cemmons/bin/aix4==> ./rumata
Trying for the 0 time
Can't send!
errno = 79
{emmons@home} /home/cemmons/bin/aix4==> ./rumata
Trying for the 0 time
Can't send!
errno = 79
{emmons@home} /home/cemmons/bin/aix4==> ./rumata
Trying for the 0 time
Can't send!
errno = 79
{emmons@home} /home/cemmons/bin/aix4==> ./rumata
Trying for the 0 time
Can't send!
errno = 79

0
emmonsCommented:
emmons, it worked!

THANKS a lot...
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.