使用tcpdump捕获服务器-客户端通信

4
我写了一个简单的服务器和客户端应用程序,可以在TCP、DCCP和UDP协议之间切换。目标是从一个应用程序向另一个应用程序传输文件,并且测量每个协议的流量,以便在不同的网络设置下进行比较(我大致知道结果应该是什么,但我需要准确的数字/图表)。然而,在将两个应用程序分别启动在不同的计算机并开始tcpdump后,我只在tcpdump日志中得到了我的4GB文件的前几MB (~50MB)。这些应用程序是用标准的C/C++代码编写的,可以在web上找到。 可能存在什么问题或者我做错了什么?
--编辑
我使用的命令行是:
tcpdump -s 1500 -w mylog
tcpdump 抓取了数据包,但仅记录了前大约55秒。这是客户端发送文件到套接字所需的时间。之后,它停止记录,即使服务器继续接收和将文件写入硬盘。
-- 编辑2
源代码:
client.cpp
server.cpp
common.hpp
common.cpp
-- 最终编辑
正如你们中的许多人指出的(也正如我怀疑的),源代码中存在几个误解/错误。在我清理了它(或几乎重写了它)之后,它能够按预期与tcpdump一起使用。我将接受@Laurent Parenteau的答案,但仅针对第5点,因为这是唯一与问题相关的。如果有人对正确的代码感兴趣,这里是它:
源代码已编辑:
client.cpp
server.cpp
common.hpp
common.cpp

1
默认情况下,tcpdump仅捕获每个数据包中的前几个字节。您是否使用“-s snaplen”参数告诉它捕获所有内容? - nos
@nos,谢谢!我试过了,但还是没有运气。请看我的编辑。 - stefita
你能否发布用于捕获网络流量的 tcpdump 命令? - Laurent Parenteau
@Laurent Parenteau:是的,在另一端已经完整接收了该文件。 - stefita
你在哪里执行捕获操作?在中间主机上吗?还是在其中一个主机上? - ereOn
显示剩余8条评论
5个回答

7

代码中有很多问题。

  1. 文件大小/传输大小被硬编码为4294967295字节。如果提供的文件不足这么多字节,就会出现问题。
  2. 在发送方,您没有检查文件读取是否成功。因此,如果文件小于4294967295个字节,您将不知道它并且会向网络发送垃圾数据(或根本不发送任何数据)。
  3. 当使用UDP和DDCP时,数据包的顺序不能保证,因此接收到的数据可能是乱序的(即垃圾数据)。
  4. 当使用UDP时,丢失的数据包不会进行重传,因此某些数据可能永远无法接收。
  5. 在接收器中,您没有检查接收到的字节数,而是始终将MAX_LINE字节写入文件。因此,即使您接收0个字节,您仍将写入文件,这是错误的。
  6. 当使用UDP时,由于您正在紧密循环中发送数据,即使write()调用返回与请求发送的字节数相同的字节数,网络堆栈或网络接口也可能会丢弃大量数据,因为没有拥塞控制。因此,您需要自己实施一些拥塞控制。

这只是对代码的快速扫描,其中可能还存在更多问题...

我的建议是: 使用TCP进行传输,对读取/发送的文件进行md5sum,对接收/保存的文件进行md5sum,并比较这两个md5sum。一旦您完成了这个案例,就可以开始测试(仍然使用md5sum比较)UDP和DCCP...

对于tcpdump命令,您应将-s 1500更改为-s 0,这意味着无限制。使用该tcpdump命令,您可以相信它没有看到的数据尚未被发送/接收。另一件好事是将发送方的tcpdump输出与接收方进行比较。这样,您就会知道两个网络堆栈之间是否发生了某些数据包丢失。


  1. 和 2. 是合理的,但仅用于测试目的并使源代码紧凑。3.、4. 和 6. 也是已知的,测试的目的不是实现可靠的传输应用程序,而是测试协议性能(主要是带宽)。5. 是个好点子,我会改变它。我已经尝试使用 TCP 进行测试,并且文件可以正常到达,无论我为 snaplen 放置了什么值,tcp 都不会滞后55秒左右。
- stefita
接收器在此之后还能接收多长时间的数据?我问这个问题是因为数据可能已经被接收,但仍然在堆栈缓冲区中(尚未被应用程序读取)。这可能解释了网络传输时间和读取应用程序中的所有内容并将其写入文件所需的时间之间的小差异。 - Laurent Parenteau
将文件的其余部分写入磁盘需要超过一分钟的时间。tcpdump仅捕获少量通信。如果我开始FTP传输,则它会捕获所有数据包... - stefita
1
关于您之前的评论“测试的目的不是实现可靠的传输应用程序,而是测试协议性能(主要是带宽)”。如果有很多数据包丢失,性能看起来会比实际情况更好。当然,除非最终应用程序不关心数据包丢失和可靠的通信... - Laurent Parenteau
关于发送和接收文件的md5sum...那个文件是重复模式还是大部分是随机数据? - Laurent Parenteau
1
@stefita - tcpdump正在捕获所有被发送的数据包。你代码中的许多错误掩盖了它实际上没有发送你认为它发送的大部分数据的事实。接收方似乎继续“接收”,因为你代码中的错误导致它在没有接收任何数据时仍将数据写入文件。tcpdump运行完美。 - Omnifarious

3

你是否拥有x项访问权限?改用Wireshark并尝试使用它-它是免费的,开源的,并且可能比tcpdump更广泛地使用。 (它以前被称为Ethereal。)

另外,请尝试以下tcpdump选项:

  • -xx打印数据包的链接标头和数据(-w写入数据吗?)
  • -C显式指定最大文件大小。
  • -U逐个将数据包写入文件而不是刷新缓冲区。
  • -p不要将网卡置于混杂模式
  • -O不要使用数据包匹配优化器,因为您正在使用新的应用程序级协议。
  • 您是否在tcpdump中使用详细输出?这会使缓冲区很快填满,因此在运行时将stdout / err重定向到文件。

这两端都使用千兆以太网卡吗?


Wireshark也使用tcpdump/libpcap,所以不会有任何区别。 - stefita
2
libpcap是一个数据包捕获库,而tcpdump和wireshark是两个不同的应用程序,它们都使用它。我猜这是一个应用程序级别或配置问题,而不是库的问题。 - carlsborg
@stefita:是“不会”还是“不行”?你试过了吗? - default

2

tcpdump被全球数万名程序员和计算机安全专业人士用作诊断和法医工具。当这样的工具似乎处理一个非常普通的任务时出现问题,首先要怀疑的是你编写的代码,而不是工具本身。

在这个特定案例中,你的代码有各种重大错误。特别是,在TCP协议下,即使客户端没有发送任何数据,你的服务器仍将继续向文件写入数据。

该代码存在竞争条件,会导致某些情况下的不确定行为,错误地将 '\0' 视为网络数据中的特殊值,忽略错误条件和文件结束条件。这只是简略阅读的结果。

在这种情况下,我几乎可以确定 tcpdump 的功能完美无误,并告诉你,你的应用程序并不像你想象的那样运行。


2
“这是客户端需要将文件发送到套接字的时间。之后,即使服务器继续接收和写入文件到硬盘,客户端也会停止。”这听起来很奇怪。套接字缓冲区太小,不可能发生这种情况。我认为你的服务器代码只是似乎在接收数据,而发送方实际上已经停止发送数据了。

0

我知道这可能听起来很傻,但你确定不是文件的flush()问题吗?也就是说,数据仍然在内存中,还没有写入磁盘(因为它们的数量不足)。

尝试使用sync或者等待一段时间,直到你确定已经传输了足够的数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接