UDP packet sending and receiving - how to calculate time consumed?
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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.
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
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.
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
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;
}
Last edited by dwhitney67; 06-05-2012 at 09:48 AM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.