title: Time measure UDP socket C
body: <p>I´m trying to obtain the performance in a Client (PC i7 3.4 GHz Kubuntu 15.04) - Server (RaspberryPi 700 Mhz Raspbian Jessie) architecture with sockets,  measuring the spent time sending and receiving with at least microseconds precision.</p>
  
  <p>Concretely, I have a client (PC) that makes 100 times:</p>
  
  <ul>
  <li>Send UDP frame to server (Ta)</li>
  <li>Receive UDP frame from server (Tb)</li>
  <li>Spent time is: T=Tb-Ta</li>
  </ul>
  
  <p>and a server (RaspberryPi) that makes 100 times:</p>
  
  <ul>
  <li>Receive UDP frame from client(T1)</li>
  <li>Send UDP frame from client(T2)</li>
  <li>Spent time is: T'=T2-T1</li>
  </ul>
  
  <p>I´m measuring time before send and after receive in client and subtracting it the time taken in server to receive and send, so the total time would be: 
  Tt=T-T' 
  but sometimes I get negative measures... :S</p>
  
  <p>I´m measuring with this macro, where in 'X' I placed my code (C:sendto()-recvfrom() or S:recvfrom()-sendto()):</p>
  
  <pre><code>float timef=0.0;
  #define TIME_MEASURE(X)                                        \
  {                                                              \
    struct timespec ts1, ts2;                                    \
    clock_gettime( CLOCK_REALTIME, &amp;ts1 );                       \
    X;                                                           \
    clock_gettime( CLOCK_REALTIME, &amp;ts2 );                       \
    timef=(float) ( 1.0*(1.0*ts2.tv_nsec - ts1.tv_nsec*1.0)*1e-9 \
      + 1.0*ts2.tv_sec - 1.0*ts1.tv_sec ) );                     \
  }
  
  //Client pseudo-code example
  
  main(){
     TIME_MEASURE(
         while(i&lt;100)
         {
             sendto(...);
             recvfrom(..);
         }
     );
  }
  </code></pre>
  
  <p>I have to measure time in any case, so another solution to obtain performance is not valid for me.</p>
  
  <p>Can anyone suggest what can I do to solve this problem?</p>
  
  <p>Than you so much.</p>
  
  <p><strong>(V2. EDITED WITH 'int64_t' and 'double' VALUES)</strong></p>
  
  <p>Here is my full code.</p>
  
  <p>It can be downloaded from:<br>
  V1 - 
  <a href="https://www.dropbox.com/sh/gb4mhn3amkyqhc1/AAC6FxKCfDxXQYgzRsjArvXQa?dl=0" rel="nofollow">https://www.dropbox.com/sh/gb4mhn3amkyqhc1/AAC6FxKCfDxXQYgzRsjArvXQa?dl=0</a></p>
  
  <p>V2 - 
  <a href="https://www.dropbox.com/sh/byipa75qruc71gj/AAD2ExMlnQSaUk_Pbc5xR2lZa?dl=0" rel="nofollow">https://www.dropbox.com/sh/byipa75qruc71gj/AAD2ExMlnQSaUk_Pbc5xR2lZa?dl=0</a></p>
  
  <p>server.c:</p>
  
  <pre><code>    /****************************************
   * Servidor UDP. Recibe como argumento
   * en linea de comandos el numero de puerto. El servidor
   * se ejecuta en bucle
   ***************************************/
  #include &lt;sys/types.h&gt;
  #include &lt;netdb.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;string.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;arpa/inet.h&gt;
  #include &lt;pthread.h&gt;
  #define TAMANO 256
  
  #include &lt;sys/time.h&gt;
  #include &lt;math.h&gt;
  #include &lt;time.h&gt;
  
  void * ack();
  void error_fatal(char *); /* Imprime un mensaje de error y sale del programa */
  
  
  
  
  int sock, length, fromlen, n, i, j, port ;
  struct sockaddr_in server;
  struct sockaddr_in from;
  char buffer[TAMANO];
  
  float timeArr;
  float timeVector[101];
  double timed;
  
  #define TIME_MEASURE(X)                                             \
  {                                                                   \
      struct timespec ts1, ts2, diff;                                 \
      clock_gettime( CLOCK_REALTIME, &amp;ts1 );                          \
      X;                                                              \
      clock_gettime( CLOCK_REALTIME, &amp;ts2 );                          \
      timeArr= (float) ( 1.0*(1.0*ts2.tv_nsec - ts1.tv_nsec*1.0)*1e-9 \
       + 1.0*ts2.tv_sec - 1.0*ts1.tv_sec );                           \
       diff.tv_sec = ts2.tv_sec - ts1.tv_sec;                          \
       diff.tv_nsec = ts2.tv_nsec - ts1.tv_nsec;                       \
       if( diff.tv_nsec &lt; 0 ) {                                        \
           diff.tv_sec--;                                              \
           diff.tv_nsec += 1000000000LL;                               \
           }                                                               \
           printf( "Elapsed: %u.%09lld secs\n", diff.tv_sec, diff.tv_nsec );\
           const int64_t NANO = 1000000000LL;                              \
           int64_t nsec = (int64_t)(ts2.tv_sec - ts1.tv_sec) * NANO;       \
           nsec += (int64_t)(ts2.tv_nsec - ts1.tv_nsec);                   \
           printf( "Elapsed nsec: %lld.%09lld secs\n", nsec / NANO, nsec % NANO );\
           timed = (double)nsec * 1e-9;                                    \
           printf("nsec=%ld\n");                                           \
           }\
  
  int main(int argc, char *argv[])
  {
  
      timeArr=0.1;
      i=0;
      pthread_t recv;
  
      FILE *f;
  
  
  
  
      if (argc &lt; 2) 
      {
          fprintf(stderr, "ERROR, no se ha indicado el puerto \n");
          exit(1);
      }
  
      /* obtain port number */
      if (sscanf(argv[1], "%d", &amp;port) &lt;= 0)
      {
          fprintf(stderr, "%s: error: wrong parameter: port\n", argv[0]);
      return -2;
      }
  
      /* (1) creacion del socket del servidor*/
      sock=socket(AF_INET, SOCK_DGRAM, 0);
      if (sock &lt; 0) 
          error_fatal("Creando el socket");
  
      length = sizeof(server);
      memset(&amp;server,0,length); /*limpio la direccion del socket del servidor*/
  
      /* (2) vinculo la direccion IP y puerto local al socket creado anteriormente */
      server.sin_family=AF_INET;
      server.sin_addr.s_addr=INADDR_ANY;
      server.sin_port=htons(port);
  
      if (bind(sock,(struct sockaddr *)&amp;server,length)&lt;0)
          error_fatal("binding");
  
      fromlen = sizeof(struct sockaddr_in);
  
      /* (3) bucle principal. Pongo a recibir y responder mensajes a traves del socket*/
      printf("Servidor listo y esperando tramas UDP en el puerto %d...\n", port);
  
  
  
      while (1) 
      {
          //el cliente manda una trama de prueba para no contar el tiempo de espera en el servidor
          //client sends init frame and it is not counted
          if(i==0)
          {
               //Recibo paquete de prueba para empezar a contar, desecho este tiempo
              n = recvfrom(sock,buffer,TAMANO,0,(struct sockaddr *)&amp;from,&amp;fromlen);
              pthread_create (&amp;recv, NULL,ack, &amp;fromlen);
              i++;            
  
          }
          else
          {
  
              TIME_MEASURE(
  
                  n = recvfrom(sock,buffer,TAMANO,0,(struct sockaddr *)&amp;from,&amp;fromlen);
  
                  if (n &lt; 0) 
                      error_fatal("recvfrom");
                      /*datagrama recibido*/
  
                  pthread_create (&amp;recv, NULL,ack, &amp;fromlen);
              );
  
  
              timeVector[i]=(float)timeArr;
  
              printf("timevector[%d] = %f\n", i, timeArr);
  
              if(i==100)
              {
                  f=fopen("dataserver.txt", "w+");
                  printf("Se han recibido 100 tramas UDP\n\n\n");
  
                  for(j=0;j&lt;=100;j++)
                  {
  
                      fprintf(f,"%f\n",timeVector[j]);
                      //printf("valores: %f\n",timeVector[j]);
                  }
                  i=0;
                  fclose(f);
                  memset(timeVector,0,100);
              }
              else
              {
                  i++;   
              }
          }
  
      }
      return 0;
  }
  
  void *ack(void *ptr){
  
      int *fl;
  
      fl= (int *)ptr;
      buffer[n]='\0'; /* para poder imprimirlo con prinft*/
      //printf("Recibido en el servidor: %s\n", buffer);
  
      /*enviar respuesta*/
      float t;
  
      t=(float)timeArr;
  
      //It is like an ACK, now I am not using this value
      n = sendto(sock,&amp;t,sizeof(float),0,(struct sockaddr *)&amp;from,fromlen);
  
      memset(buffer,0,TAMANO); 
      if (n &lt; 0) 
           error_fatal("sendto"); 
  
      pthread_exit(NULL);
  }
  
  void error_fatal(char *msg)
  {
   perror(msg);
   exit(1);
  }
  </code></pre>
  
  <p>client.c</p>
  
  <pre><code>/*******************************************************************
   * Cliente de eco remoto sobre UDP:
   *
   * cliente dir_ip_maquina puerto
   ********************************************************************/
  #include &lt;sys/types.h&gt;
  #include &lt;netdb.h&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;string.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;arpa/inet.h&gt;
  #define TAMANO 256 /* tamano del buffer de recepcion */
  
  #include &lt;sys/time.h&gt;
  #include &lt;math.h&gt;
  #include &lt;time.h&gt;
  
  void error_fatal(char *); /* Imprime un mensaje de error y sale del programa */
  
  float timeArr;
  float timeVector[101];
  int i;
  double timed;
  
  
  
  #define TIME_MEASURE(X)                                             \
  {                                                                   \
      struct timespec ts1, ts2, diff;                                 \
      clock_gettime( CLOCK_REALTIME, &amp;ts1 );                          \
      X;                                                              \
      clock_gettime( CLOCK_REALTIME, &amp;ts2 );                          \
      timeArr= (float) ( 1.0*(1.0*ts2.tv_nsec - ts1.tv_nsec*1.0)*1e-9 \
       + 1.0*ts2.tv_sec - 1.0*ts1.tv_sec );                           \
       diff.tv_sec = ts2.tv_sec - ts1.tv_sec;                          \
       diff.tv_nsec = ts2.tv_nsec - ts1.tv_nsec;                       \
       if( diff.tv_nsec &lt; 0 ) {                                        \
           diff.tv_sec--;                                              \
           diff.tv_nsec += 1000000000LL;                               \
           }                                                               \
           printf( "Elapsed: %u.%09lld secs\n", diff.tv_sec, diff.tv_nsec );\
           const int64_t NANO = 1000000000LL;                              \
           int64_t nsec = (int64_t)(ts2.tv_sec - ts1.tv_sec) * NANO;       \
           nsec += (int64_t)(ts2.tv_nsec - ts1.tv_nsec);                   \
           printf( "Elapsed nsec: %lld.%09lld secs\n", nsec / NANO, nsec % NANO );\
           timed = (double)nsec * 1e-9;                                    \
           printf("nsec=%ld\n");                                           \
           }\
  
  
  
  /*
   * 
   *    const int64_t NANO = 1000000000LL;                              \
      int64_t nsec = (int64_t)(ts2.tv_sec - ts1.tv_sec) * NANO;       \
      nsec += (int64_t)(ts2.tv_nsec - ts1.tv_nsec);                   \
      printf( "Elapsed: %lld.%09lld secs\n", nsec / NANO, nsec % NANO );\
                                                                      \
  
                                                                      */
  
  int main(int argc, char *argv[])
  {
      int sock; /* descriptor del socket del cliente */
      int length, n, j, port;
      struct sockaddr_in server, from; /* direcciones del socket del servidor y cliente */
      struct hostent *hp; /* estructura para el nombre del servidor (ver gethostbyname) */
      char buffer[TAMANO]; /* buffer de recepcion y envio del mensaje */
      char buffercpy[TAMANO];
      float bufferf[7];
  
      FILE *f = fopen("data.txt", "w+");
      struct timespec spec;
      clockid_t clk_id;
  
      clk_id=CLOCK_REALTIME;
      i=0;
  
  
      if (argc != 3) 
      { 
          fprintf(stderr,"Uso: ./client server port\n");
          exit(1);
      }
  
      /* obtain port number */
      if (sscanf(argv[2], "%d", &amp;port) &lt;= 0)
      {
      fprintf(stderr, "%s: error: wrong parameter: port\n", argv[0]);
      return -2;
      }
      printf("El cliente va a mandar por el puerto %d\n", port);
  
      /* (1) creacion del socket UDP del cliente */
      sock= socket(AF_INET, SOCK_DGRAM, 0); 
      if (sock &lt; 0)   
          error_fatal("socket");    
      server.sin_family = AF_INET; /*dominio de Internet*/
  
      /* (2) averigua la direccion IP a partir del nombre del servidor*/
      hp = gethostbyname(argv[1]);
      if (hp==0) 
          error_fatal("Host desconocido");
  
      /* (3) copia la IP resuelta anteriormente en la direccion del socket del servidor */
      memcpy((char *)&amp;server.sin_addr,(char *)hp-&gt;h_addr,hp-&gt;h_length);
  
     if ( clock_getres( clk_id, &amp;spec) == -1 )
     {
        perror( "clock get resolution" );
        return EXIT_FAILURE;
      }
  
      //printf ("CLOCK_REALTIME: %ld s, %ld ns\n", spec.tv_sec,spec.tv_nsec); 
  
      /* (4) copia el puerto destino en la direccion del socket del servidor */
      server.sin_port = htons(port);
      length=sizeof(struct sockaddr_in);
  
      printf("Por favor, introduce el mensaje: ");
          memset(buffer,0,TAMANO); /*limpio el buffer*/
          fgets(buffer,TAMANO-1,stdin);
          strcpy(buffercpy, buffer);//Copio el mensaje a un nuevo buffer para que se repita en el while
  
  
      while(i&lt;=100)
      {       
          //client sends init frame and it is not counted
          if(i==0)
          {
  
              /* (5) envia al socket del servidor el mensaje almacenado en el buffer*/
              n=sendto(sock,buffer,strlen(buffer),0,(struct sockaddr *) &amp;server,length);
              if (n &lt; 0) 
                  error_fatal("Sendto");
  
              /* (6) lee del socket el mensaje de respuesta del servidor*/
              n = recvfrom(sock,bufferf,sizeof(float),0,(struct sockaddr *) &amp;from, &amp;length);
  
              if (n &lt; 0) 
                  error_fatal("recvfrom");
              i++;
  
          }
          else
          {
  
  
  
  
              TIME_MEASURE(
                  memset(buffer, '\0', sizeof(buffer));
                  strcpy(buffer, buffercpy);
  
                  /* (5) envia al socket del servidor el mensaje almacenado en el buffer*/
                  n=sendto(sock,buffer,strlen(buffer),0,(struct sockaddr *) &amp;server,length);
                  if (n &lt; 0) 
                      error_fatal("Sendto");
  
                  /* (6) lee del socket el mensaje de respuesta del servidor*/
                  n = recvfrom(sock,bufferf,sizeof(float),0,(struct sockaddr *) &amp;from, &amp;length);
  
                  if (n &lt; 0) 
                      error_fatal("recvfrom");
  
              );
  
              timeVector[i]=(float)timeArr;
              printf("Tiempo de procesamiento cliente - timeVector [%d]: %f\n", i,timeArr);
  
              //timeVector[i]+=(float)(0.0 - *bufferf);
              //printf("timeVector negativo[%d]= %f\n", i, timeVector[i]);
              buffer[n]='\0'; /* para poder imprimirlo con printf*/
              bufferf[n]='\0'; /* para poder imprimirlo con printf*/
              //printf("Recibido en el cliente: %f ACK(%d)%c\n",*bufferf,i,'\0');
  
  
              printf("timeVector TOTAL= %f\n\n", timeVector[i]);
              //printf("buffer=%s%c\n",buffer,'\0');
  
              if(i==100){
                  for(j=1;j&lt;=100;j++){
                      fprintf(f,"%f\n",timeVector[j]);
                          //printf("valores: %f\n",timeVector[j]);
                  }
                  printf("Se han enviado 100 tramas UDP \n\n\n");
  
              }
              i++;
          }
      }
  
      fclose(f);
      /*cerramos el socket*/
      if(close(sock) &lt; 0) 
          error_fatal("close");
  }
  
  void error_fatal(char *msg)
  {
      perror(msg);
      exit(1);
  }
  </code></pre>
  
  <p>I get warnings in number formats, so I think that it is probably that printed values wouldn't be correct.</p>
  
  <p>These are warnings which I get:  </p>
  
  <pre><code>server.c: In function ‘main’:
  server.c:50:18: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘__time_t {aka long int}’ [-Wformat=]
            printf( "Elapsed: %u.%09lld secs\n", diff.tv_sec, diff.tv_nsec );\
                    ^
  server.c:122:13: note: in expansion of macro ‘TIME_MEASURE’
               TIME_MEASURE(
               ^
  server.c:50:18: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 3 has type ‘__syscall_slong_t {aka long int}’ [-Wformat=]
            printf( "Elapsed: %u.%09lld secs\n", diff.tv_sec, diff.tv_nsec );\
                    ^
  server.c:122:13: note: in expansion of macro ‘TIME_MEASURE’
               TIME_MEASURE(
               ^
  server.c:54:18: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 2 has type ‘long int’ [-Wformat=]
            printf( "Elapsed nsec: %lld.%09lld secs\n", nsec / NANO, nsec % NANO )
                    ^
  server.c:122:13: note: in expansion of macro ‘TIME_MEASURE’
               TIME_MEASURE(
               ^
  server.c:54:18: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 3 has type ‘long int’ [-Wformat=]
            printf( "Elapsed nsec: %lld.%09lld secs\n", nsec / NANO, nsec % NANO )
                    ^
  server.c:122:13: note: in expansion of macro ‘TIME_MEASURE’
               TIME_MEASURE(
               ^
  server.c:56:17: warning: format ‘%ld’ expects a matching ‘long int’ argument [-Wformat=]
            printf("nsec=%ld\n");                                           \
                   ^
  server.c:122:13: note: in expansion of macro ‘TIME_MEASURE’
               TIME_MEASURE(
               ^
  </code></pre>