【问题标题】:How can I verify that a TCP packet has received an ACK in C#?如何在 C# 中验证 TCP 数据包是否已收到 ACK?
【发布时间】:2026-02-04 18:20:03
【问题描述】:

使用阻塞/非阻塞方法发送一些tcp数据后,例如:

Socket.Send() or Socket.SendAsync()

我怎么知道我的数据收到了 ACK 消息?

.NET 能否知道 TCP 数据是否已成功发送?

【问题讨论】:

  • .NET Framework 将此类任务委托给 Windows Sockets API,因此您无需关心这些。如果发生任何严重的事情,您将收到 SocketException 对象。请注意,您误解了文档。 SendAsync 将在调用后立即返回。数据发送任务正在后台执行。这就是异步模式。
  • 更正了问题以避免混淆。我正在尝试关注如何知道您的数据何时已被连接的另一端接受。

标签: c# .net tcp


【解决方案1】:

确定的唯一方法是实现某种应用程序级别的确认。 TCP 级别的“ACK”数据包根本不会暴露给应用程序级别,因此您必须使用更多的东西。

【讨论】:

  • ACK 的频率也不是应用程序可以控制的。某些优化,例如对于高延迟的网络链接可能会显着改变行为。 blogs.technet.com/mrsnrub/archive/2009/05/26/…
  • 例如... SharpPcap 或 Pcap.Net?我不确定为什么这是公认的答案,因为它没有回答所提出的问题。
【解决方案2】:

你让另一端回应它。

即使 TCP 已经 Acked 了,如果接收端在处理消息并对其采取行动之前终止(出于好的或坏的原因),你仍然不知道,所以唯一知道的方法是让另一端告诉你。

【讨论】:

    【解决方案3】:

    此信息无法从 .net 的类库中获得。当我开始用 C# 开发这个端口扫描器时,我也有同样的考虑。为了获取此类信息,我使用了 libpcap 的 .NET 包装器(安装相应的驱动程序后)SharpPcap (http://sourceforge.net/projects/sharppcap/)。 ACK 数据包是通过 SharpPcap 的接口获得的(透明地调用本地 libpcap 接口)。

    我的应用程序是 NScanner Port Scanner/Sweeper,您可以在 codeplex 找到代码,参考我对上述库 (http://nscanner.codeplex.com/) 的简单使用。

    希望我能帮上忙。

    【讨论】:

    • Sharppcap +1。使用过滤器“tcp”和“目标 ip 地址”创建一个嗅探器,以匹配期望 ack 的主机。然后解析 TCP 标头并检查字段以匹配预期的 ack 回复。如果您无法找到发出的 ack 请求,只需使用发送 ack 请求的主机的“tcp”和“源 IP 地址”实例化另一个嗅探器。
    【解决方案4】:

    “我正在尝试关注如何知道您的数据何时已被连接的另一端接受。”

    我认为您需要了解您将实施哪种类型的应用层协议以及这对应用程序性能有何影响。

    以 HTTP 作为“流式传输”协议的示例。服务器向客户端发布数据流。不再有额外的应用层“ACK”,服务器实际上并不关心他的数据流何时以及如何准确到达。这对高延迟链接非常有效。

    现在将其与 SMB 进行比较!不是流式传输文件,而是将数据划分为块。每个成功传输的数据块都会在应用层得到确认。这为您提供了更多控制权,但是,它有效地杀死了 WAN 网络上的协议(查看“带宽延迟产品”)。

    考虑到这一点,您可以为您的自定义协议提出自己的设计。

    【讨论】:

      【解决方案5】:

      我推荐使用Pcap.Net

      您可以在 C# 中使用此库轻松嗅探数据包,然后轻松检查数据包值。

      您还可以轻松构建和发送数据包。

      【讨论】:

        【解决方案6】:

        如果您确实需要了解 TCP 连接的数据包级别详细信息,那么除了创建用于发送的 TCP 套接字之外,您还需要您的应用程序使用 winpcap API 来查看原始流量.您可以安装过滤器以仅接收与确定远程端的特定 IP、端口组合相关的数据包。

        有几个项目为 libpcap 创建 .NET 包装器,例如 here

        【讨论】:

          【解决方案7】:

          TCP 层会不断重发数据包,直到收到成功的 ACK。

          在发生这种情况之前,Send 将阻塞 - SendAsync 不会阻塞,您可以在 TCP 层处理发送数据包时继续处理其他内容。

          【讨论】:

          • 这很好,但同样,您如何以编程方式知道您的数据是正确到达还是失败?
          • 只发送块直到用户缓冲区被复制到内核。从应用程序的角度来看,Send 与实际的消息传输和重试无关。