使用CLOSE_WAIT套接字写入时避免Go中的数据丢失

时间:2014-09-30 20:58:35

标签: sockets tcp go

  1. 使用netcat -l <​​/ li>开始侦听客户端
  2. go program将net.DialTCP打开一个conn给所述客户端。
  3. 杀死netcat
  4. 在go程序中,用[]字节执行conn.Write() - &gt;它运行正常,没有错误!
  5. 它需要另一个conn.Write来获取错误:broken pipe
  6. 第一次写入是数据丢失发生的,我想避免。如果我只收到错误,我知道我可以保留数据并稍后再试。 我已经看到https://stackoverflow.com/a/15071574/2757887这是一个非常类似的情况,解释似乎适用于此,但它仍然没有解释如何处理这个问题,如果我需要实现的tcp协议只做单向通信。

    我用wireshark嗅到了流量,当我杀死netcat时,我可以看到它将FIN发送到go程序,go程序用ACK回复。出于某种原因,go程序没有立即用它自己的FIN回复 - 而且我很好奇为什么会这样,它可能对我的问题有所帮助 - 但是它可能有充分的理由。

    无论哪种方式,从“连接终止”部分@ http://en.wikipedia.org/wiki/Transmission_Control_Protocol,我得出结论,此时套接字处于CLOSE_WAIT状态,我也用“netstat -np”确认,它显示套接字正在进行杀死netstat后从ESTABLISHED到CLOSE_WAIT。

    查看wireshark,第一个conn.write会生成一个包含push和ack字段的数据包,当然还有我的有效负载。这是写得很好的写作。

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

    所以我的问题是:

    A)为什么我不能在第一次写入时出错?如果套接字收到FIN并且处于CLOSE_WAIT状态,为什么Go让我写入套接字并告诉我一切正常?
    B)有什么方法可以检查Go是否套接字是在CLOSE_WAIT?如果是这样,我可以为此目的考虑它关闭而不是写。

    感谢, 迪特

1 个答案:

答案 0 :(得分:3)

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