RoundTrip测试RTT时延

网络时间同步(NTP)原理

网络时钟同步的工作过程如下:

  • Device A发送一个NTP报文给Device B,该报文带有它离开Device A时的时间戳,该时间戳为10:00:00am(T1)。

  • 当此NTP报文到达Device B时,Device B加上自己的时间戳,该时间戳为11:00:01am(T2)。

  • 当此NTP报文离开Device B时,Device B再加上自己的时间戳,该时间戳为11:00:02am(T3)。

  • 当Device A接收到该响应报文时,Device A的本地时间为10:00:03am(T4)。

NTP报文的往返时延Delay=(T4-T1)-(T3-T2)

Device A相对Device B的时间差offset=((T2-T1)+(T3-T4))/2

RounTrip代码分析

RoundTrip就是按照NTP时间同步的原理,实现一个测量两台机器之间时间误差的程序,在实现中服务端将收到数据的时间与发送应答的时间抽象为一个时间点,即忽略server端处理数据的时间误差。

代码位置:

  • UDP with muduo:muduo- master/examples/roundtrip/roundtrip_udp.cc
  • TCP with muduo:muduo- master/examples/roundtrip/roundtrip.cc

roundtrip_udp.cc服务端

c 复制代码
void serverReadCallback(int sockfd, muduo::Timestamp receiveTime)
{
  int64_t message[2];
  struct sockaddr peerAddr;
  bzero(&peerAddr, sizeof peerAddr);
  socklen_t addrLen = sizeof peerAddr;
  ssize_t nr = ::recvfrom(sockfd, message, sizeof message, 0, &peerAddr, &addrLen);

  char addrStr[32];
  sockets::toIpPort(addrStr, sizeof addrStr, *reinterpret_cast<struct sockaddr_in*>(&peerAddr));
  LOG_DEBUG << "received " << nr << " bytes from " << addrStr;

  if (nr < 0)
  {
    LOG_SYSERR << "::recvfrom";
  }
  else if (implicit_cast<size_t>(nr) == frameLen)
  {
  	// 记录一个时间戳 并返回给客户端
    message[1] = receiveTime.microSecondsSinceEpoch();
    ssize_t nw = ::sendto(sockfd, message, sizeof message, 0, &peerAddr, addrLen);
    if (nw < 0)
    {
      LOG_SYSERR << "::sendto";
    }
    else if (implicit_cast<size_t>(nw) != frameLen)
    {
      LOG_ERROR << "Expect " << frameLen << " bytes, wrote " << nw << " bytes.";
    }
  }
  else
  {
    LOG_ERROR << "Expect " << frameLen << " bytes, received " << nr << " bytes.";
  }
}

roundtrip_udp.cc客户端

c 复制代码
void sendMyTime(int sockfd)
{
  int64_t message[2] = { 0, 0 };
  // 发送一个当下的时间戳
  message[0] = Timestamp::now().microSecondsSinceEpoch();
  ssize_t nw = sockets::write(sockfd, message, sizeof message);
  if (nw < 0)
  {
    LOG_SYSERR << "::write";
  }
  else if (implicit_cast<size_t>(nw) != frameLen)
  {
    LOG_ERROR << "Expect " << frameLen << " bytes, wrote " << nw << " bytes.";
  }
}

void clientReadCallback(int sockfd, muduo::Timestamp receiveTime)
{
  int64_t message[2];
  ssize_t nr = sockets::read(sockfd, message, sizeof message);

  if (nr < 0)
  {
    LOG_SYSERR << "::read";
  }
  else if (implicit_cast<size_t>(nr) == frameLen)
  {
    int64_t send = message[0];
    int64_t their = message[1];
    int64_t back = receiveTime.microSecondsSinceEpoch();
    int64_t mine = (back+send)/2;	
    LOG_INFO << "round trip " << back - send	// 往返时间
             << " clock error " << their - mine;	// 服务端相对客户端的时钟差
  }
  else
  {
    LOG_ERROR << "Expect " << frameLen << " bytes, received " << nr << " bytes.";
  }
}

roundtrip.cc Tcp的代码与上面类似

测试

同一机器下(127.0.0.1)

udp

shell 复制代码
20240506 13:14:09.259012Z 18477 INFO  round trip 707 clock error 66 - roundtrip_udp.cc:93
20240506 13:14:09.461553Z 18477 INFO  round trip 828 clock error 66 - roundtrip_udp.cc:93
20240506 13:14:09.662840Z 18477 INFO  round trip 952 clock error 57 - roundtrip_udp.cc:93
20240506 13:14:09.863861Z 18477 INFO  round trip 755 clock error 59 - roundtrip_udp.cc:93
20240506 13:14:10.064963Z 18477 INFO  round trip 855 clock error 71 - roundtrip_udp.cc:93
20240506 13:14:10.267029Z 18477 INFO  round trip 966 clock error -23 - roundtrip_udp.cc:93
20240506 13:14:10.470978Z 18477 INFO  round trip 829 clock error 40 - roundtrip_udp.cc:93
20240506 13:14:10.671284Z 18477 INFO  round trip 841 clock error 64 - roundtrip_udp.cc:93
20240506 13:14:10.872879Z 18477 INFO  round trip 951 clock error 97 - roundtrip_udp.cc:93
20240506 13:14:11.074060Z 18477 INFO  round trip 716 clock error 66 - roundtrip_udp.cc:93
20240506 13:14:11.275834Z 18477 INFO  round trip 873 clock error 38 - roundtrip_udp.cc:93
20240506 13:14:11.477013Z 18477 INFO  round trip 897 clock error 102 - roundtrip_udp.cc:93
20240506 13:14:11.679080Z 18477 INFO  round trip 741 clock error 70 - roundtrip_udp.cc:9 

tcp

shell 复制代码
20240506 13:14:13.321049Z 11109 INFO  round trip 1108 clock error -97 - roundtrip.cc:82
20240506 13:14:13.531021Z 11109 INFO  round trip 1079 clock error -79 - roundtrip.cc:82
20240506 13:14:13.740006Z 11109 INFO  round trip 1299 clock error -46 - roundtrip.cc:82
20240506 13:14:13.943726Z 11109 INFO  round trip 1104 clock error -89 - roundtrip.cc:82
20240506 13:14:14.148380Z 11109 INFO  round trip 1158 clock error -91 - roundtrip.cc:82
20240506 13:14:14.350723Z 11109 INFO  round trip 1295 clock error 89 - roundtrip.cc:82
20240506 13:14:14.551261Z 11109 INFO  round trip 1245 clock error -113 - roundtrip.cc:82
20240506 13:14:14.758256Z 11109 INFO  round trip 1744 clock error -351 - roundtrip.cc:82
20240506 13:14:14.962002Z 11109 INFO  round trip 1276 clock error -5 - roundtrip.cc:82
20240506 13:14:15.169267Z 11109 INFO  round trip 955 clock error -46 - roundtrip.cc:82
20240506 13:14:15.374836Z 11109 INFO  round trip 1113 clock error -108 - roundtrip.cc:82
20240506 13:14:15.579069Z 11109 INFO  round trip 1125 clock error -61 - roundtrip.cc:82
20240506 13:14:15.780133Z 11109 INFO  round trip 1013 clock error -63 - roundtrip.cc:82

round trip指代的是往返时间,clock error指代的是服务端相对客户端的时钟差,单位都是微秒。

总体相比,tcp所用的往返时间还是比udp的往返时间要长,而在同一机器下,理想状态下,时钟差应该为0才对,但是两种方式都各自计算出了不怎么接近0的数值。

相关推荐
音徽编程2 小时前
Rust异步运行时框架tokio保姆级教程
开发语言·网络·rust
幺零九零零3 小时前
【C++】socket套接字编程
linux·服务器·网络·c++
23zhgjx-NanKon4 小时前
华为eNSP:QinQ
网络·安全·华为
23zhgjx-NanKon4 小时前
华为eNSP:mux-vlan
网络·安全·华为
点点滴滴的记录4 小时前
RPC核心实现原理
网络·网络协议·rpc
Lionhacker5 小时前
网络工程师这个行业可以一直干到退休吗?
网络·数据库·网络安全·黑客·黑客技术
程思扬5 小时前
为什么Uptime+Kuma本地部署与远程使用是网站监控新选择?
linux·服务器·网络·经验分享·后端·网络协议·1024程序员节
ZachOn1y5 小时前
计算机网络:运输层 —— 运输层概述
网络·tcp/ip·计算机网络·运输层
佚明zj5 小时前
【点云网络】voxelnet 和 pointpillar
网络
转世成为计算机大神5 小时前
网关 Spring Cloud Gateway
java·网络·spring boot·1024程序员节