英文:
golang write net conn without returning error but the other side of the socket can't receive data
问题
// 只有数据
func (self *Packet) WriteData(w io.Writer) error {
n := len(self.Data)
data := self.Data[0:n]
for n > 0 {
wn, err := w.Write(data)
data = data[wn:n]
n -= wn
if err != nil {
return err
}
}
return nil
}
当我使用 net.Dial("tcp") 创建的 net.Conn 调用 WriteData 函数时,它返回 nil,但是套接字的另一端有时无法接收到发送的数据。
看起来连接已经断开,但是 w.Write 仍然没有返回错误。
在我看来,当套接字的另一端没有接收到数据包时,w.Write 不应该返回而没有错误,所以我是否遗漏了什么?
英文:
// only Data
func (self *Packet) WriteData(w io.Writer) error {
n := len(self.Data)
data := self.Data[0:n]
for n > 0 {
wn, err := w.Write(data)
data = data[wn:n]
n -= wn
if err != nil {
return err
}
}
return nil
}
When I call the WriteData function with a net.Conn (created by net.Dial("tcp")), it returns nil but the other port of the socket can't receive the sent data sometimes.
It seems the connection was broken, but w.Write still returns without error.
In my mind w.Write shouldn't return without error when the other side of this socket doesn't receive the packet, so is there something I missed?
答案1
得分: 2
这是TCP协议工作原理的一个功能。在发送之前,无法确定是否发送到了一个关闭的套接字(即使有,发送和关闭也会竞争)。
如果远程套接字关闭,最终会收到一个错误,如“broken pipe”或“connection reset by peer”。由于伯克利套接字API的原因,通常直到第二次发送操作才会看到这个错误。这依赖于远程主机响应一个RST,或者中间代理发送一个ICMP信号,所以如果数据包延迟或丢失,你仍然可以继续发送而不会出错。
唯一可靠地检测到关闭连接的方法是从连接中读取,并获得一个0字节的响应,这在Go语言中被翻译为EOF。
英文:
This is a function of how the TCP protocol works. There's is no way to determine if you're sending to a closed socket before hand (even if there were, sending and closing would race).
If a remote socket is closed, you will eventually get an error, broken pipe
or connection reset by peer
. Simply because of the berkley socket api, you often won't see this until your second send operation. This relies on the remote host responding with an RST, or an intermediary sending an ICMP signal, so it still is possible that if the packets are delayed or lost, and you can continue sending without an error.
The only way to reliably detect a closed connection is to Read from a connection, and and get a 0 byte response, which go translates to EOF.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论