Muduo 网络编程示例之五: 测量两台机器的网络延迟

简介:

Muduo 网络编程示例之五: 测量两台机器的网络延迟

陈硕 (giantchen_AT_gmail)

Blog.csdn.net/Solstice  t.sina.com.cn/giantchen

这是《Muduo 网络编程示例》系列的第五篇文章。

Muduo 全系列文章列表: http://blog.csdn.net/Solstice/category/779646.aspx

本文介绍一个简单的网络程序 roundtrip,用于测量两台机器之间的网络延迟,即“往返时间 / round trip time / RTT”。这篇文章主要考察定长 TCP 消息的分包,TCP_NODELAY 的作用。

本文的代码见 http://code.google.com/p/muduo/source/browse/trunk/examples/roundtrip/roundtrip.cc

测量 RTT 的办法很简单:

  • host A 发一条消息给 host B,其中包含 host A 发送消息的本地时间
  • host B 收到之后立刻把消息 echo 回 host A
  • host A 收到消息之后,用当前时间减去消息中的时间就得到了 RTT。

NTP 协议的工作原理与之类似,不过,除了测量 RTT,NTP 还需要知道两台机器之间的时间差 (clock offset),这样才能校准时间。

roundtrip_ntp

以上是 NTP 协议收发消息的协议,RTT = (T4-T1) – (T3-T2),时间差 = ((T4+T1)-(T2+T3))/2。NTP 的要求是往返路径上的单程延迟要尽量相等,这样才能减少系统误差。偶然误差由单程延迟的不确定性决定。

在我设计的 roundtrip 示例程序中,协议有所简化:

roundtrip_simple

简化之后的协议少取一次时间,因为 server 收到消息之后立刻发送回 client,耗时很少(若干微秒),基本不影响最终结果。

我设计的消息格式是 16 字节定长消息:

roundtrip_msg

T1 和 T2 都是 muduo::Timestamp,一个 int64_t,表示从 Epoch 到现在的微秒数。

为了让消息的单程往返时间接近,server 和 client 发送的消息都是 16 bytes,这样做到对称。

由于是定长消息,可以不必使用 codec,在 message callback 中直接用

while (buffer->readableBytes() >= frameLen) { ... } 就能 decode。

请读者思考,如果把 while 换成 if 会有什么后果?

client 程序以 200ms 为间隔发送消息,在收到消息之后打印 RTT 和 clock offset。一次运作实例如下:

roundtrip_example

这个例子中,client 和 server 的时钟不是完全对准的,server 的时间快了 850 us,用 roundtrip 程序能测量出这个时间差。有了这个时间差就能校正分布式系统中测量得到的消息延迟。

比方说以上图为例,server 在它本地 1.235000 时刻发送了一条消息,client 在它本地 1.234300 收到这条消息,直接计算的话延迟是 –700us。这个结果肯定是错的,因为 server 和 client 不在一个时钟域(这是数字电路中的概念),它们的时间直接相减无意义。如果我们已经测量得到 server 比 client 快 850us,那么做用这个数据一次校正: -700+850 = 150us,这个结果就比较符合实际了。当然,在实际应用中,clock offset 要经过一个低通滤波才能使用,不然偶然性太大。

请读者思考,为什么不能直接以 RTT/2 作为两天机器之间收发消息的单程延迟?

这个程序在局域网中使用没有问题,如果在广域网上使用,而且 RTT 大于 200ms,那么受 Nagle 算法影响,测量结果是错误的(具体分析留作练习,这能测试对 Nagle 的理解),这时候我们需要设置 TCP_NODELAY 参数,让程序在广域网上也能正常工作。




    本文转自 陈硕  博客园博客,原文链接:http://www.cnblogs.com/Solstice/archive/2011/04/20/2021859.html,如需转载请自行联系原作者



相关文章
|
3月前
|
移动开发 网络协议 NoSQL
不为人知的网络编程(十七):冰山之下,一次网络请求背后的技术秘密
本文将抛弃千篇一律的计网知识理论,从现实的互联网技术实践角度,一步步为你分享一次网络请求背后的技术秘密。
68 0
|
29天前
|
域名解析 缓存 网络协议
优化Lua-cURL:减少网络请求延迟的实用方法
优化Lua-cURL:减少网络请求延迟的实用方法
|
1月前
|
Web App开发 网络协议 安全
网络编程懒人入门(十六):手把手教你使用网络编程抓包神器Wireshark
Wireshark是一款开源和跨平台的抓包工具。它通过调用操作系统底层的API,直接捕获网卡上的数据包,因此捕获的数据包详细、功能强大。但Wireshark本身稍显复杂,本文将以用抓包实例,手把手带你一步步用好Wireshark,并真正理解抓到的数据包的各项含义。
103 2
|
2月前
|
网络安全 Python
Python网络编程小示例:生成CIDR表示的IP地址范围
本文介绍了如何使用Python生成CIDR表示的IP地址范围,通过解析CIDR字符串,将其转换为二进制形式,应用子网掩码,最终生成该CIDR块内所有可用的IP地址列表。示例代码利用了Python的`ipaddress`模块,展示了从指定CIDR表达式中提取所有IP地址的过程。
66 6
|
2月前
|
网络协议 数据挖掘 5G
适用于金融和交易应用的低延迟网络:技术、架构与应用
适用于金融和交易应用的低延迟网络:技术、架构与应用
88 5
|
4月前
|
存储 机器人 Linux
Netty(二)-服务端网络编程常见网络IO模型讲解
Netty(二)-服务端网络编程常见网络IO模型讲解
|
4月前
|
网络协议 Python
告别网络编程迷雾!Python Socket编程基础与实战,让你秒变网络达人!
在网络编程的世界里,Socket编程是连接数据与服务的关键桥梁。对于初学者,这往往是最棘手的部分。本文将用Python带你轻松入门Socket编程,从创建TCP服务器与客户端的基础搭建,到处理并发连接的实战技巧,逐步揭开网络编程的神秘面纱。通过具体的代码示例,我们将掌握Socket的基本概念与操作,让你成为网络编程的高手。无论是简单的数据传输还是复杂的并发处理,Python都能助你一臂之力。希望这篇文章成为你网络编程旅程的良好开端。
70 3
|
3月前
|
JSON API 开发者
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
深入解析Python网络编程与Web开发:urllib、requests和http模块的功能、用法及在构建现代网络应用中的关键作用
32 0
|
4月前
|
网络协议 安全 网络安全
C语言 网络编程(四)常见网络模型
这段内容介绍了目前被广泛接受的三种网络模型:OSI七层模型、TCP五层模型以及TCP/IP四层模型,并简述了多个网络协议的功能与特性,包括HTTP、HTTPS、FTP、DNS、SMTP、TCP、UDP、IP、ICMP、ARP、RARP及SSH协议等,同时提到了ssh的免费开源实现openssh及其在Linux系统中的应用。
|
5月前
|
安全 Java 网络安全
【认知革命】JAVA网络编程新视角:重新定义URL与URLConnection,让网络资源触手可及!
【认知革命】JAVA网络编程新视角:重新定义URL与URLConnection,让网络资源触手可及!
56 2