【发布时间】:2014-09-30 20:58:34
【问题描述】:
- 用 netcat -l 开始监听客户端
- go 程序使用 net.DialTCP 向所述客户端打开一个连接。
- 杀死网猫
- 在 go 程序中,使用 []byte 执行 conn.Write() -> 运行良好且没有错误!
- 需要另一个 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,那么如何区分这些情况呢?