有没有办法告诉操作系统丢弃任何缓冲的传出TCP数据?

时间:2011-02-01 02:32:09

标签: c sockets tcp

我在基于TCP的客户端软件中遇到了一个有趣/恼人的情况,它是这样的:

  1. 我的客户端进程在笔记本电脑上运行,它通过TCP连接到我的服务器进程(在LAN上的另一台机器上运行)
  2. 不负责任的用户在客户端传输TCP数据时将以太网电缆从笔记本电脑中拉出来
  3. 客户端进程继续使用一些额外的TCP数据调用send(),填满操作系统的SO_SNDBUF缓冲区,直到......
  4. 通知客户端进程(通过MacOS / X的SCDynamicStoreCallback功能)以太网接口已关闭,并通过在其TCP套接字上调用close()进行响应
  5. 通过两到五秒......
  6. 用户将以太网电缆插回
  7. 通知客户端进程该接口已备份,并自动重新连接到服务器
  8. 这一切都很有效......除了通常还有一个不需要的步骤8,这就是:

    0.8。在步骤4中close()的TCP套接字恢复(!)并发送该套接字的内核出站数据缓冲区中的其余数据。发生这种情况是因为操作系统在释放套接字之前尝试传递所有出站TCP数据...通常是件好事,但在这种情况下我宁愿没有发生这种情况。

    所以,问题是,有没有办法告诉TCP层丢弃其SO_SNDBUF中的数据?如果是这样,我可以在关闭()之前在步骤4中的死套接字之前进行该调用,并且在旧套接字被放弃之后我不必担心来自旧套接字的僵尸数据到达服务器。

2 个答案:

答案 0 :(得分:1)

这(从两个不同的TCP连接收到的数据不是相互排序的)是TCP / IP的基本属性。你不应该通过清除发送缓冲区来尝试解决它 - 这很脆弱。相反,您应该修复应用程序以在应用程序层处理此可能性。

例如,如果您从已认为已连接的客户端接收服务器端的新连接,则应该删除现有连接。

此外,该过程的第4步有点可疑。实际上,您应该等到TCP报告错误(或连接上发生应用程序级别超时) - 正如您所注意到的,如果物理断开连接只是一个简短的TCP,TCP将恢复。

答案 1 :(得分:0)

如果要在步骤4关闭套接字时丢弃正在等待传输的任何数据,则在关闭之前将SO_LINGER设置为0。