【问题标题】:Determine TCP payload activity/statistics确定 TCP 有效负载活动/统计信息
【发布时间】:2013-08-22 15:07:54
【问题描述】:

我想查找给定文件描述符或给定接口的 TCP 有效负载活动计数器(接收的总字节数)。最好是给定的文件描述符,但对于接口就足够了。理想情况下,我真的很想知道任何已确认的字节,即使是我尚未读入用户空间的字节(还没有?)。

我已经看到 getsockopt()TCP_INFO 功能,但据我所知,似乎没有一个字段存储“接收的总字节数”或“传输的总字节数(例如确认)”。

我还看到了接口的 netlink IFLA_STATS+RTNL_TC_BYTESSIOCETHTOOL+ETHTOOL_GSTATS ioctl()rx_bytes 字段),这些都很棒,但我没有不认为他们能够区分其他层的开销/标头和实际有效负载字节。

procfs/proc/net/tcp 但这似乎也不包含我要查找的内容。

有什么方法可以获取这些特定的数据吗?

编辑:混杂模式对吞吐量有无法承受的影响,所以我无法利用任何使用它的东西。更不用说实现大部分 IP 堆栈来确定哪些数据包是合适的,这超出了我对这个解决方案的预期范围。

目标是对我从 recvmsg() 存储的值有一个总体/不信任/第二次猜测。

正确的做法是正确跟踪这些值,但如果有一个简单的“嘿操作系统?我在此套接字上真正收到了多少字节?”会很有价值。

【问题讨论】:

  • 您可以使用iptables 进行计数。这个答案很有趣:superuser.com/a/264651
  • 你可以使用 libpcap 吗?您可以设置监控接口并准确捕获您想要的数据包类型,然后如果这些数据包符合您的条件,只需增加一个计数器。

标签: linux networking tcp


【解决方案1】:

也可以使用带有 SIOCINQ 的 ioctl 调用来获取接收缓冲区中排队的未读数据量。以下是手册页中的用法:http://man7.org/linux/man-pages/man7/tcp.7.html

int value;
error = ioctl(tcp_socket_fd, SIOCINQ, &value);

对于接口 TCP 统计信息,我们可以使用“netstat -i -p tcp”来查找每个接口的统计信息。

【讨论】:

  • 这很有帮助。这不是我所希望的整个shebang,而是一个很好的信息。
  • 只要我们在讨论解决方案,也可以考虑通过添加新的 IOCTL 值来扩展 TCP 层的 IOCTL 调用。您可以在此处找到定义 SIOCINQ 的位置:lxr.free-electrons.com/source/net/ipv4/tcp.c#L535。基本上,添加一个新结构,它将返回您正在寻找的所有自定义统计信息。显然,这将比混杂模式解决方案更有效。明显的警告是,需要为此编译内核,也许您的用例可能不允许您这样做。
  • 是的,我的意思是将其定义为超出范围。但也许我应该麻烦在上游提交它。
【解决方案2】:

您希望将其用于诊断还是用于开发?

如果进行诊断,tcpdump 可以准确地告诉您网络上发生了什么,通过端口和主机详细信息进行过滤。

如果是为了开发,也许更多关于你想要达到的目标的信息会有所帮助......

ifconfig 给出 RX 和 TX 的总数。

ifconfig 从 /proc/net/dev 获取这些详细信息(您可以通过 strace ifconfig 看到)。

还有 netstat -t 给出的 Send/Receive-Q 值,如果这更接近您想要的值。

【讨论】:

  • 开发:我想对我从recvmsg() 存储的值有一个总体/不信任/第二次猜测。 ifconfig 包括来自 TCP 下层的开销。 netstat -t 的 Receive-Q 值受到抽样错误风险的困扰。为了获得可靠的数字,我可能多久采样一次?值本身多久发布一次到procfs
  • 我怀疑 procfs 值始终是最新的 - 它不是真正的文件,它是动态生成的。
  • 也许,如果这是作为一种审计机制,你应该在执行recv'ing的代码和使用数据的代码之间放置一些东西。无论是在相同的代码中,还是在一个完全独立的进程中,代理数据并计算过去的数据量。如果不是为了审计,你确定你不想自己统计到目前为止读取的字节数吗?
【解决方案3】:

也许 /proc/net/dev 中的统计信息可以提供帮助。我不熟悉计算有效负载与包括标头在内的完整数据包,因此这使问题更难回答。

至于单个文件描述符的统计数据,我不知道有任何标准方法可以获取该信息。

如果可以控制需要统计信息的程序的启动,则可以使用“拦截器”库来实现自己的 read()、write()、sendto() 和 recvfrom() 调用,将调用传递给标准 C 库(或直接传递给系统调用),保留活动计数器,并找到发布这些值的方法。

【讨论】:

  • 这些数字会在某个时候重置吗?这些是终生数字吗?
  • 这些数字在系统重新启动时重置。可能有一种方法可以在重新启动之间重置它们 - 如果是这样,我希望系统实用程序或 /proc 接口可以提供该功能。此外,如果接口是可插拔的,则应在移除和重新创建接口时重置统计信息。
【解决方案4】:

如果您不想只计算每个接口的总 RX/TX(ifconfig/iproute2 工具中已经提供)...

如果您进一步研究 /proc,您可以获得更多信息。更具体地说是/proc/<pid>/net/dev

样本输出:

    Inter-|   Receive                                                |  Transmit
 face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
  eth0: 12106810846 8527175    0 15842    0     0          0    682866 198923814 1503063    0    0    0     0       0          0
    lo: 270255057 3992930    0    0    0     0          0         0 270255057 3992930    0    0    0     0       0          0
  sit0:       0       0    0    0    0     0          0         0        0       0    0    0    0     0       0          0

如果您开始查找,信息来自net/core/net-procfs.c 来自Linux kernel(procfs 仅使用此信息)。当然,所有这些都意味着您需要特定的流程来跟踪。

您可以仔细阅读 /proc 中提供的信息,或者如果您需要更稳定的东西,那么专门为您的应用程序复制 net-procfs 功能可能是有意义的。

【讨论】:

    猜你喜欢
    • 2010-10-31
    • 1970-01-01
    • 2016-01-28
    • 2020-01-07
    • 2011-04-28
    • 2019-04-06
    • 2016-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多