-1

I am trying to create my first UDP client server program in C language slightly modified from the man page of linux gai_strerror(3) - Linux man page. Although that I am using several error functions to check the correct process of the code when I reach the transmission part it fails. Based on what I see the connection is correct there is no error so in theory the message should be transmitted, but in practice it fails. I even open wireshark on local mode to see if there are any data transmitted, but nothing is transmitted. Since this is my first client Server program, and I am new into programing I can not think any other way to debug my code. What am I missing?

Addition:

On the terminal two things are printed:

connected: Success

and the error that is printing is Error sending data!

Any advice would be much appreciated.

#include <sys/types.h>
#include<errno.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <inttypes.h>
#include <sys/time.h> /* The header includes gettimeofday() */  
#include <time.h>  /* The header includes time types which we will use for day time */
#include <math.h>  /* The header includes mathematical declarations */

int main(int argc, char *argv[]) {

 struct timeval start; /* struct timeval for tv_sec and tv_usec */
 struct addrinfo bind_info;
 struct addrinfo *servInfo, *rp; /* addrinfo is filled with destination host information */
 int socket_fd, retrieve_info; /* socket_fd represents the file descriptor of socket, rtt round time trip */
 ssize_t send;

 uint32_t tran = 0;
 char *ip_serv = argv[1]; /* Set argv[1] as the server IP */
 char *port_number = argv[2];

 memset(&bind_info, 0, sizeof(struct addrinfo));
 bind_info.ai_family = AF_INET;
 bind_info.ai_socktype = SOCK_DGRAM;
 bind_info.ai_protocol = IPPROTO_UDP;
 bind_info.ai_flags = AI_PASSIVE;

 if ((retrieve_info = getaddrinfo(ip_serv, port_number,&bind_info, &servInfo)) !=0 ) {
   fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(retrieve_info));
   exit(EXIT_FAILURE);
 }

 for (rp = servInfo; rp != NULL; rp = rp->ai_next) {

   if ((socket_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) == -1) {
     perror("socket");
     continue;
   }

   if (connect(socket_fd, rp->ai_addr, rp->ai_addrlen) != -1) {
     perror("connected");
     break; /* We made it enough stop */
   }
   close(socket_fd); /* Release socket after binding */
  }

  if (rp == NULL) {
    fprintf(stderr, "failed to connect\n");
    exit(2);
  }

  freeaddrinfo(servInfo);

  gettimeofday(&start, NULL); /* timezone should be NULL */

  long int start_time = (start.tv_sec * 1000000 + start.tv_usec);

  tran = htonl(start_time);

  send = sendto(socket_fd,&tran,sizeof(tran),0,(struct sockaddr *) rp->ai_addr, rp->ai_addrlen);

  if (send == 0) {
    printf("Transmission to server was correct!\n");
  }
  else {
    fprintf(stderr, "Error sending data!\n");
  }
  exit(0);
 } /* end of int main (argv[]) */
Thanos
  • 1,618
  • 4
  • 28
  • 49
  • First of all, TL;DR! Please narrow down the code to the minimal needed to replicate the problem, a so called [SSCCE](http://sscce.org/). Then, *how* does it fail? Does a `send` call return `-1`? If so, what's the error? Otherwise, have you tried monitoring your network with e.g. [Wireshark](http://www.wireshark.org/)? There's no firewall anywhere that blocks your packages? – Some programmer dude Mar 19 '14 at 11:42
  • Did I miss the memo? Is it 'Bad Formatting Day'? – Martin James Mar 19 '14 at 11:55
  • I tried to minimize my code as much as possible. On the terminal two things are printed: `connected: Success` and the error that is printing is `Error sending data!` – Thanos Mar 19 '14 at 12:05
  • @MartinJames I tried to format the code to be in readable format, but I am not that familiar with the web page. I tried to follow the instructions but as I said I am beginner. Thank you for your time and effort reviewing my question, even with bad formatting. – Thanos Mar 19 '14 at 12:08
  • Your calculation of `start_time` might not be correct. The number of seconds since the POSIX epoch (January 1, 1970) is well over a billion. Multiplying a billion with a million will overflow the range of a `long int` if it's still 32 value. – Some programmer dude Mar 20 '14 at 08:28
  • @JoachimPileborg Well I found the reference [here](http://stackoverflow.com/questions/5362577/c-gettimeofday-for-computing-time) about the the `gettimeofday()` function. I tried actually both: `time_t now = time(0); = 1395305898` and `gettimeofday(&start, NULL); = 1395305898304695`. I am trying to get as accurate result as possible, so I decided to use the `gettimeofday()`. Do you think that I should use uint64_t? – Thanos Mar 20 '14 at 09:14
  • @Thanos To be on the safe side, yes. Also, to make sure the conversions are safe, use `1000000ULL` to make the literal an unsigned 64-bit value as well as that will make the whole expression an `unsigned long long`. – Some programmer dude Mar 20 '14 at 10:02
  • @JoachimPileborg True is better to stay on the safe side. I transformed the number to `start_time = 1395320935644823` and `htonll = 1395320935644823`. I made the conversion based on a code that I found [hton long long](http://cboard.cprogramming.com/c-programming/103733-hton-long-long.html) it looks interesting. Again thank you for your assistance step by step. – Thanos Mar 20 '14 at 13:13

1 Answers1

0

You should read the manual page for sendto, as you seem to not understand its return value.

It will return the number of bytes it sent, or -1 on error. If it fails the call will set errno just like any other system call, and you can use perror like you do for the other functions when they fail.

So in your case you will say that the call was successful when the call have sent zero bytes, and say that the call failed in all other cases (which includes actual successful sending).

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Finally I start understanding more about it. I am using now perror() on all functions appropriate and it gave me an unexpected error. `sendto: Invalid argument` I looked over the net and I found that it means that one of the elements passed into the function might not have correct format. I checked all the elements and I even convert the int that I want to transmit with htonl(). I think that also sizeof() the htonl int is wrong, so I am using the size of the orriginal int before conversion. So I assume the problem is coming from the socket, but since there is no print error on socket? – Thanos Mar 20 '14 at 00:20
  • @Thanos First of all, don't use `perror` (or check `errno`) unless a function actually *fails*. Your use of `perror` for the `connect` call is wrong. The same goes for the `sendto` call, only check `errno` and use `perror` if sendto` returns `-1`. – Some programmer dude Mar 20 '14 at 08:22
  • I understand what you mean. It would make more sense to use a condition something like: `if (sendto == -1) { perror("sendto");}` I am sorry the continuous questions but I am a total beginner in programming and it seams that I do not understand everything correctly. One last thing, since I have the error on `sendto()` and from man page: `ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);` The only error is `const void *buf` I am using int should I convert it? Thank you in advance. – Thanos Mar 20 '14 at 09:39
  • @Thanos Your `sendto` call is otherwise correct. You do have a couple of other problems though, one is that you use `AI_PASSIVE` flag to `getaddrinfo`, that flag should only be use for listening (server) sockets. Another problem is that you use `connect` even though you use UDP sockets, and UDP sockets are unconnected. – Some programmer dude Mar 20 '14 at 10:01
  • To be honest I was wondering about that too, but the reason is that I saw it on the man page of [gai_strerror(3) - Linux man page](linux.die.net/man/3/gai_strerror). So I thought is a valid source of information and I used this code. But the problem still remains even if I do not use connect. I still get this error: `sendto: Invalid argument`, even when I remove the `AI_PASSIVE` flag. – Thanos Mar 20 '14 at 12:44