Sockets 使用CLOSE_WAIT socket写入时避免Go中的数据丢失 使用netcat-l启动侦听客户端 go程序通过net.DialTCP打开与所述客户端的连接 杀死网猫 在go程序中,使用[]字节执行conn.Write()->运行正常,没有错误 需要另一个conn.Write才能得到错误:管道破裂

Sockets 使用CLOSE_WAIT socket写入时避免Go中的数据丢失 使用netcat-l启动侦听客户端 go程序通过net.DialTCP打开与所述客户端的连接 杀死网猫 在go程序中,使用[]字节执行conn.Write()->运行正常,没有错误 需要另一个conn.Write才能得到错误:管道破裂,sockets,tcp,go,Sockets,Tcp,Go,第一次写入是发生数据丢失的情况,我希望避免这种情况。如果我只得到一个错误,我知道我可以保留数据,稍后再试。 我看到了一个非常类似的情况,这里的解释似乎适用,但它仍然没有解释如何处理这个问题,如果我需要实现的tcp协议只进行单向通信的话 我用wireshark嗅到了流量,当我杀死netcat时,我可以看到它向go程序发送FIN,go程序用ACK回复。出于某种原因,go程序不会立即用自己的FIN进行响应——我很好奇为什么会这样,它可能会帮助解决我的问题——但这可能有一个很好的理由 无论哪种方式,从“

第一次写入是发生数据丢失的情况,我希望避免这种情况。如果我只得到一个错误,我知道我可以保留数据,稍后再试。 我看到了一个非常类似的情况,这里的解释似乎适用,但它仍然没有解释如何处理这个问题,如果我需要实现的tcp协议只进行单向通信的话

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

无论哪种方式,从“连接终止”部分@,我断定套接字此时处于关闭等待状态,我也用“netstat-np”确认了这一点,这表明套接字在杀死netstat后从已建立状态变为关闭等待状态

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

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

所以我的问题是:

A) 为什么我在第一次写入时不能得到一个错误?如果插座收到FIN且处于关闭状态,请稍候,为什么让我给插座写信并告诉我一切正常?
B) 有没有办法让我检查一下Go插座是否处于关闭状态?如果是这样,我可以为此考虑关闭,不写。 谢谢,
Dieter

基本上,成功的
写入
只会告诉您数据已排队发送到另一端。如果您需要确保另一端获取该数据,即使连接关闭或出现错误,您也必须存储该数据的副本,直到另一端向您提供应用程序级确认。

您正在从套接字读取数据吗?阅读将告诉您有关netcat关闭插座的信息。(请注意,这就是socket API的工作方式,无论您使用哪种语言,2.write都会发出错误信号)它将如何告诉我?我刚刚试过——记住,这是tcp协议中的单向通信——我的结果:*如果我提供一个字节数组,它就挂起了(没有人在写另一端)*如果我提供一个空字节数组,我在建立连接时和在关闭等待时都会得到EOF,你会得到EOF。当然,您必须在执行写操作的同时执行读操作。我不明白这个解决方案应该如何工作。正如我所说,两种情况(已确定和关闭等待)都给出了EOF,那么如何区分这两种情况呢?大卫,你说的可能是正确的。但正如我所解释的,我必须在单向应用程序协议的约束下工作。同样,如果netstat可以看到套接字处于关闭状态,为什么我的代码不能?@user2757887您不能在这些约束条件下工作。你将永远有一个比赛条件。您需要应用程序级别的确认。为什么我不能?你能解释一下比赛情况吗?它甚至可能不适用于这种情况。。因为我的协议是幂等的(多次发送相同的数据没有坏处)并且不是实时的,所以在建立连接之后重试发送数据要安全得多,而不是在套接字处于关闭状态时考虑处理数据_wait@user2757887哦,如果连接中断,只需重新发送最后几条消息。这并不完美,但可能已经足够好了。@user2757887插座可以随时关闭。您的write()调用可能会将数据推到电线上,就在数据到达另一端之前,接收器会关闭插座或起火。或者,它接收数据,发送TCP ack,然后在TCP堆栈将数据交付给接收应用程序之前触发。