【问题标题】:Avoiding dataloss in Go when writing with CLOSE_WAIT socket使用 CLOSE_WAIT 套接字写入时避免 Go 中的数据丢失
【发布时间】:2014-09-30 20:58:34
【问题描述】:
  1. 用 netcat -l 开始监听客户端
  2. go 程序使用 net.DialTCP 向所述客户端打开一个连接。
  3. 杀死网猫
  4. 在 go 程序中,使用 []byte 执行 conn.Write() -> 运行良好且没有错误!
  5. 需要另一个 conn.Write 才能得到错误:损坏的管道

第一次写入是发生数据丢失的地方,我想避免。如果我只收到一个错误,我知道我可以保留数据并稍后再试。 我见过https://stackoverflow.com/a/15071574/2757887 这是一个非常相似的案例,解释似乎适用于这里,但它仍然没有解释如何处理这个问题,如果我需要实现的 tcp 协议只进行单向通信。

我已经用wireshark嗅探了流量,当我杀死netcat时,我可以看到它向go程序发送了FIN,go程序用ACK回复它。由于某种原因,go 程序没有立即回复它自己的 FIN - 我很好奇为什么会这样,它可能有助于解决我的问题 - 但可能有一个很好的理由。

无论哪种方式,从“连接终止”部分@http://en.wikipedia.org/wiki/Transmission_Control_Protocol,我得出结论,此时套接字处于 CLOSE_WAIT 状态,我还用“netstat -np”确认了这一点,这表明套接字从 ESTABLISHED杀死 netstat 后到 CLOSE_WAIT。

查看wireshark,第一个conn.write 会生成一个设置了push 和ack 字段的数据包,当然还有我的payload。这是在 go 中成功的写入。

然后曾经属于netstat的旧socket发送RST, 这可以确保一旦我尝试写入 go(第二次写入)它就会失败。

所以我的问题是:

A) 为什么我在第一次写入时不会出错?如果套接字收到 FIN 并且处于 CLOSE_WAIT 状态,为什么 Go 让我写入套接字并告诉我一切都很好?
B) 有什么方法可以在 Go 中检查套接字是否处于 CLOSE_WAIT 状态?如果是这样,我可以为此考虑将其关闭而不进行写入。

谢谢, 迪特

【问题讨论】:

  • 你是从套接字读取的吗?阅读将告诉您有关 netcat 关闭套接字的信息。 (请注意,这就是套接字 API 的工作方式,无论您使用哪种语言 2. write 都会发出错误信号)
  • 它将如何告诉我?我刚刚尝试过——记住,这是 tcp 协议中的一种通信方式——我的结果:*如果我提供一个字节数组,它就会挂起(没有人在写另一端..)*如果我提供一个 字节数组,我在建立连接时得到EOF,以及在close_wait中
  • 你会得到EOF。当然,您必须在执行写入的同时进行读取。
  • 我不明白这个解决方案应该如何工作。就像我说的,两种情况(已建立和 close_wait)都会给出 EOF,那么如何区分这些情况呢?

标签: sockets tcp go


【解决方案1】:

从根本上说,成功的write 只会告诉您数据已排队等待发送到另一端。如果您需要确保另一端获得该数据,即使连接关闭或出错,您必须存储数据的副本,直到另一端为您提供应用程序级确认。

【讨论】:

  • 大卫,你说的可能是正确的。但就像我解释的那样,我必须在单向应用程序协议的约束下工作。同样,如果 netstat 可以看到套接字处于 close_wait 状态,为什么我的代码不能?
  • @user2757887 你不能在这些限制下工作。您将始终处于竞争状态。您需要应用程序级别的确认。
  • 为什么我不能?你能解释一下比赛条件是什么吗?它甚至可能不适用于这种情况..因为我的协议是幂等的(多次发送相同的数据没有害处)并且不是实时的,所以稍后在建立连接时重试发送数据要安全得多,而不是考虑它当socket处于close_wait时处理
  • @user2757887 哦,如果连接中断,只需重新发送最后几条消息。这并不完美,但可能已经足够好了。
  • @user2757887 可以随时关闭套接字。您的 write() 调用可能会将数据推送到线路上,并且就在它到达另一端之前,接收器关闭套接字或着火。或者它可能接收到数据,发送一个 TCP 确认,然后在 TCP 堆栈将数据传递给接收应用程序之前着火。
猜你喜欢
  • 1970-01-01
  • 2018-03-21
  • 1970-01-01
  • 2022-06-13
  • 1970-01-01
  • 1970-01-01
  • 2015-06-24
  • 1970-01-01
  • 2011-03-31
相关资源
最近更新 更多