golang write net conn without returning error but the other side of the socket can't receive data

huangapple go评论123阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2015年3月3日 19:21:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/28830549.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定