套接字通过并发 FTP 传输接收错误数据

Socket receiving wrong data with concurrent FTP transfer

有一个讨厌的线程(客户端)正在等待来自远程设备(服务器)的事件。这些事件由专用网络通过 TCP 套接字接收(我必须分配一个静态 IP)。该操作不是阻塞操作,而是轮询 (select + recv)。对于某个操作,线程使用 CURL 库启动与设备的 FTP 传输。然后,有时,我们收到的不是下一个正常操作,而是垃圾。该行为可以系统地在三台计算机中的两台上重现。如果设备直接通过网络端口连接,则其中之一可以工作,但如果通过网络 USB 适配器(允许 Internet 连接)则无法工作。另一方面,在这种情况下,适配器在另一台计算机上运行良好。 如果我们消除 FTP 传输,一切正常。 行为与使用的 CURL 版本和最后一个 7.40 相同。

我是这里的维护者,有一个古老的巨大项目,我几乎无法 change/rewrite 事情,特别是在这种情况下,这段代码显然已经工作了好几年(尽管有些问题已被告知)距离测试版只有将近两个月的时间。但我必须解决这个问题,如果有必要,我会将操作从轮询更改为阻塞,例如。其他同事已经看到代码,Application Verifier 没有检测到任何东西(不再),从 recv 接收到的缓冲区已经损坏,Wireshark 说我们正在接收正确的数据包 - 什么都没有!调试有点困难,因为没有针对这个巨大 "application" 的调试设置,并且通过远程调试和一些 "well chosen" 断点……错误行为消失了。我尝试了将近两周的大部分常用(过去获胜)路径,其余路径看起来也不太有前途 - 而且它们都需要时间:1)直接调试其中一台计算机(如果调试可重现并且安装 VS 后,从服务器获取整个代码)-我不知道还要尝试什么 2)编写 "right" 代码以在单独的项目中执行此操作(已经以某种方式开始) 3)替代 llvm 构建(巨大的努力)。

欢迎提出任何想法,我很乐意回应任何澄清要求。

编辑 我们在一个最小的测试程序中重现了这种情况。它发生在三台尝试过的两台计算机上的 USB - 网络适配器上。 我们通过 TCP 套接字从我们的设备获取两个命令。我们只读取第一个(1 个字节),我们使用 CURL 库进行 FTP 传输,然后我们读取另一个(7 个字节),但只有垃圾。如果我们用读取第二个命令切换 FTP 调用,一切都很好,即使是在无限循环中。 Wireshark 显示数据(7 个字节)正确,因此很明显在 CURL FTP 传输期间发生了一些事情。但是它如何影响不相关的套接字呢? 当前步骤是识别损坏套接字的 CURL 调用。

编辑 2 我们没有准确识别脏 CURL 调用,因为……它不是一个固定点。我们通过 recv(..., MSG_PEEK) 和跟踪来进行这种识别,有时它可以在两个 printf 指令之间,尽管它在同一代码区域附近。恕我直言,这是唯一可能的,因为某些 CURL 连接调用会产生另一个线程(名为 _SockAsyncThread@4,显然由 Windows 内部使用)可能会改变我们套接字的堆栈。通过在某些地方添加 Sleep(1500) ... 它起作用了。与 64 位版本相同的 "not working" 行为。虽然它从不与 CURL 一起工作,但通过将其替换为 FtpGetFile,它在一个循环中工作,除了第一次调用 :(。我的想法是 "D-Link DUB-E100 USB 2.0 Fast Ethernet Adapter" 在其内部存在一些严重的问题驱动程序(最新,Windows 7 版本与 Vista 版本相同,顺便说一句)。在我看来,一种解决方法是首先读取套接字上的通知,然后再处理它们。或者也许只是使用另一个线程来完成 FTP 工作。

这是真正是其他人代码中的错误的罕见问题之一; OP 已确认以太网设备驱动程序出现故障。