LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   UDP packet sending and receiving - how to calculate time consumed? (http://www.linuxquestions.org/questions/programming-9/udp-packet-sending-and-receiving-how-to-calculate-time-consumed-948603/)

sindhu4sind 06-05-2012 06:00 AM

UDP packet sending and receiving - how to calculate time consumed?
 
I have a implemented a udp packet sender and receiver. I want to calculate time for transaction, from sender to receiver how much time its taking..

Sender Code:
Code:

void senderFunc() {
/*some other code */
if((s1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
    error_handler("\nERROR: in Socket\n");
    memset((char *) &me, 0, sizeof(me));
    me.sin_family = AF_INET;
    me.sin_port = PORT;
    if (inet_aton(G_IP, &me.sin_addr)==0)
    {
        fprintf(stderr, "inet_aton() failed\n");
        exit(1);
    }
    printf("\Tick - %d : %s",cntr++,str);
    sprintf(b1, "%s",str);  // Some Information in b1 buffer to transfer
    if(sendto(s1, b1, sizeof(b1),0,(struct sockaddr *) &me,n)==-1)
    error_handler("\nERROR: in sendto()\n");
    close (s1);
    return;
    }
}

Receiver Code:
Code:

int receiverFunc () {
        struct sockaddr_in other, me;
        int s2, n, i = 1;
        char b2[BUFLEN];//, b2[BUFLEN];
        s2 = socket(AF_INET, SOCK_DGRAM,0);
        me.sin_family = AF_INET;
        me.sin_port = PORT;
        me.sin_addr.s_addr = htonl(INADDR_ANY);
        bind(s2,(struct sockaddr *)&me, sizeof(me));
        n=sizeof(other);
        int incr = 0;
        while (i){
                recvfrom (s2,b2,BUFLEN,0,(struct sockaddr *) &other, &n);
                printf ("\nSubnet 2: Tick - %d : %s",incr++, b2);
        }
        return 0;
}

How to calculate time if i send a packet from sender to receiver?

thanks for nice response always.. looking for your response.. :)

Sindhu.

dwhitney67 06-05-2012 06:48 AM

To calculate a time delta, you need to have a reference point in time, say T1, and another time, say T2. The delta would be T2 - T1.

If you are sending a packet to another process on your the system, then you should be able to send the current time (T1), say using a resolution in microseconds, and then upon receipt of the packet, again capture the current system time (T2) so that you can perform the calculation.

If you are sending the packet to another machine, you can still employ the same process described above, however you need to ensure that both systems have their system times in sync.

An alternative, which is employed by such tools as "ping", is to send a packet with the current time and have the receiver reply back with the same message. When the sender process receives the reply, a computation can be performed as to how long the message took to make a round-trip.

Nominal Animal 06-05-2012 09:06 AM

Quote:

Originally Posted by dwhitney67 (Post 4695906)
If you are sending the packet to another machine, you can still employ the same process described above, however you need to ensure that both systems have their system times in sync.

Unless your machines have an accurate external clock source (atomic clock, high-frequency radio clock), one-way timing is very hard to do reliably. NTP is definitely not accurate enough for that.

Quote:

Originally Posted by dwhitney67 (Post 4695906)
An alternative, which is employed by such tools as "ping", is to send a packet with the current time and have the receiver reply back with the same message.

Yes, this technique is recommended. Note that it is not necessary to have the actual timestamp in the message. It makes things simpler, but all you really need is to record the time when the original packet was sent, and when the response is received, then compare the two timestamps to get the round-trip time (RTT). To the other end, the timestamp (or identifier) is just opaque payload; it does not inspect it or use it in any way.

If both endpoints are bound (to a port), and there is only the single packet in flight at any time in either direction, then you don't need to have any kind of identifier in the UDP packet; each endpoint only needs to remember the accurate wall clock when they sent the packet, and when they received the response. It is just more robust to put the timestamp as the UDP packet payload.

My point is, it is quite difficult to find out the one-way trip duration. In fact, the round-trip time, RTT, is much more commonly used in the network environment. For most purposes one can assume that each leg takes about the same time. When there is heavy contention, or asymmetric connections (like ADSL lines, which tend to have much more bandwidth downstream than upstream), that is obviously not true; one leg tends to be faster, and one slower. Without some kind of a shared external clock, it is very difficult to find out how the RTT is divided between the two legs.

sindhu4sind 06-05-2012 09:20 AM

Quote:

Originally Posted by dwhitney67 (Post 4695906)
An alternative, which is employed by such tools as "ping", is to send a packet with the current time and have the receiver reply back with the same message. When the sender process receives the reply, a computation can be performed as to how long the message took to make a round-trip.

This seems easy solution.. But i don't want to calculate rtt. I am just looking for time consumed from sending to receiving.

Quote:

Tcon = Tr - Ts
as you mentioned about time delta..

how can i send time along with ping packet? and it will be same time as sending time using udp?

Suppose I have a buffer value 100
unsigned char buffer[100];

then how this length of payload can be calculated using ping?

Quote:

ping -c 10 -s 1024 -q 192.168.2.1
Like this is mentioned that 10 Packets with payload 1024 transmitted to ip 192.168.2.1

is this correct?
Code:

ping -c 10 -s 100 -q 192.168.2.1
....
....
10 packets transmitted, 10 received, 0% packet loss, time 8999ms

> Single Packet Time = 8999/10
> Time in seconds 0.899

is this approach right to calculate time? please make me correct if i am on mistake...

Thank you so much for reply

dwhitney67 06-05-2012 09:45 AM

The ping utility will not be able to perform custom tasks (such as one-way time computations) for you. You could develop your own ping application, which transports the current time as part of the payload. You would need to create a socket using a type of SOCK_RAW and a protocol of IPPROTO_ICMP. Creating the packet and a customized payload is not a trivial matter; you would have to set the fields within the IP header and ICMP header, and then insert the payload itself before finally computing the checksum that is included in the header.

Here's an application (note it is written using C++) that I developed a while back; it mimics the basics of the ping utility as far as computing round-trip time measurements.
Code:

/*
# Copyright (C) 2003-2011 David M. Whitney (aka "dwhitney67")
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <TCPClientSocket.h>
#include <SocketUtility.h>

#include <sys/time.h>

#include <string>
#include <iostream>
#include <iomanip>
#include <unistd.h>
#include <csignal>
#include <cstring>
#include <cassert>


bool done = false;

double ComputeMsDelay(const timeval& tbegin, const timeval& tend);
void  sigHandler(int signo);


int main(int argc, char** argv)
{
  const std::string remoteAddr = (argc > 1 ? argv[1] : "127.0.0.1");

  signal(SIGINT, sigHandler);

  try
  {
    // Create the raw socket (root-permissions required!)
    socketpp::TCPClientSocket sock(AF_INET, SOCK_RAW, IPPROTO_ICMP);

    setuid(getuid());

    // Build the IP and ICMP headers
    static const size_t IP_LEN = sizeof(ip) + sizeof(icmphdr) + sizeof(timeval);

    unsigned char datagram[IP_LEN] = {0};
    ip*          iph    = reinterpret_cast<ip*>(datagram);
    icmphdr*      icmph  = reinterpret_cast<icmphdr*>(datagram + sizeof(ip));
    timeval*      tbegin = reinterpret_cast<timeval*>(datagram + sizeof(ip) + sizeof(icmphdr));

    iph->ip_hl  = sizeof(ip) >> 2;
    iph->ip_v  = 4;
    iph->ip_tos = IPTOS_PREC_ROUTINE;
    iph->ip_len = htons(IP_LEN);
    iph->ip_id  = htons(54321);
    iph->ip_off = 0;
    iph->ip_ttl = IPDEFTTL;
    iph->ip_p  = IPPROTO_ICMP;

    in_addr_t src = inet_addr("10.0.0.2");
    in_addr_t dst = inet_addr(remoteAddr.c_str());

    memcpy(&iph->ip_src, &src, sizeof(iph->ip_src));
    memcpy(&iph->ip_dst, &dst, sizeof(iph->ip_dst));

    iph->ip_sum = socketpp::headerChecksum(reinterpret_cast<const uint16_t*>(iph), iph->ip_hl << 2);

    double totalDelay = 0;
    int    seq        = 1;

    // Send ICMP datagram
    sockaddr_in dst_sin;
    sock.fillAddress(reinterpret_cast<sockaddr*>(&dst_sin), sizeof(dst_sin), 0, remoteAddr.c_str());

    for (int id = 1; !done; ++id, ++seq)
    {
      memset((char*) icmph, 0, sizeof(icmphdr));
      gettimeofday(tbegin, 0);

      icmph->type            = ICMP_ECHO;
      icmph->code            = 0;
      icmph->un.echo.id      = htons(id);
      icmph->un.echo.sequence = htons(seq);
      icmph->checksum        = socketpp::headerChecksum(reinterpret_cast<const uint16_t*>(icmph),
                                                        sizeof(icmphdr) + sizeof(timeval));

      sock.send(std::basic_string<unsigned char>(datagram, datagram + IP_LEN), dst_sin);

      // Check if a reply is forthcoming...
      timeval timeout = {5, 0};

      if (sock.activityDetected(&timeout))
      {
        // Receive reply
        std::basic_string<unsigned char> response;
        sock >> response;

        // get the time value from the response packet
        const timeval* begin = reinterpret_cast<const timeval*>(response.data() + (IP_LEN - sizeof(timeval)));

        // Compute and display time delay
        timeval end;
        gettimeofday(&end, 0);

        const double delay = ComputeMsDelay(*begin, end);
        totalDelay += delay;

        std::cout << "time: " << delay << " ms" << std::endl;

        usleep(500000);  // delay half second before sending next ICMP packet
      }
      else
      {
        std::cout << "no response from remote host." << std::endl;
        done = true;
      }
    }

    std::cout << "\navg time: " << totalDelay / seq << " ms" << std::endl;
  }
  catch (socketpp::SocketException& e)
  {
    std::cerr << e.what() << std::endl;
    return 1;
  }
}


double ComputeMsDelay(const timeval& tbegin, const timeval& tend)
{
  time_t      secs  = tend.tv_sec  - tbegin.tv_sec;
  suseconds_t usecs = tend.tv_usec - tbegin.tv_usec;

  if (usecs < 0)
  {
    --secs;
    usecs += 1000000;
  }

  return ((double) secs + (double) usecs / 1000000) * 1000;
}


void sigHandler(int signo)
{
  done = true;
}



All times are GMT -5. The time now is 01:44 AM.