如何判断连接是由服务器还是客户端关闭的?

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

How can I judge a connection closed by server or client?

问题

我有一个处理接收数据的服务器,代码如下:

func handleRecv(conn *net.TCPConn) {
    header := make([]byte, 2)
    for {
        /**阻塞直到接收到header的长度**/
        n, err := io.ReadFull(conn, header)
        if err != nil {
            log.Error(err)
            break
        }
    }
}

我想知道根据err来判断连接是由服务器还是客户端关闭的。

英文:

I have a server which handle receiving data like this:

func handleRecv(conn *net.TCPConn) {
    header := make([]byte, 2)
    for {
        /**block until recieve len(header)**/
        n, err := io.ReadFull(conn, header)
        if err != nil {
             log.Error(err)
              break
        }
     }
 }

I would like to know which the connnection is closed by ? server or client according to err ?

答案1

得分: 2

首先,如果你在本地关闭连接,你应该在代码中知道这一点。否则,接收到io.EOF通常表示远程端发起了关闭。

如果在本地端调用了Close(),你会得到一个带有消息use of closed network connection*net.OpError。你可能只想检查net.Error接口,因为理论上它可以涵盖更多的错误条件。

if err, ok := err.(net.Error); ok {
    fmt.Error("not an io.EOF")
    fmt.Error(err.Error())
}

然而,如果在本地连接上调用了CloseRead()(虽然这不太可能,但它有其用途),这种方法不起作用。它会返回一个io.EOF,这就是为什么你仍然需要知道本地连接的情况。

如果连接由于超时而关闭,你将得到一个指示超时的net.Error

if err, ok := err.(net.Error); ok && err.Timeout() {
    fmt.Error("timeout error")
}

最后,如果你关心返回的错误,你可能不想使用io.Readfull,因为它在读取不完整时不会返回io.EOF。只需将数据读入缓冲区并自己检查读取的字节数和错误即可。

英文:

First of all, if you're closing the connection locally, you should know about it in your code. Otherwise, receiving an io.EOF generally signals that the remote side initiated a close.

If Close() was called on the local side, you get a *net.OpError with the message use of closed network connection. You may want to just check for the net.Error interface, since that would theoretically cover more error conditions.

		if err, ok := err.(net.Error); ok {
			fmt.Error("not an io.EOF")
			fmt.Error(err.Error())
		}

This doesn't work however if CloseRead() was called on the local connection (which isn't very likely, but it has its uses). That will return an io.EOF, and is why you still need to know what's happening to the connection locally.

If the connection was closed due to a timeout, you will get a net.Error indicating the timeout:

		if err, ok := err.(net.Error); ok && err.Timeout() {
			fmt.Error("timeout error")
		}

Finally, if you are concerned about the error returned, you may not want to use io.Readfull, which doesn't return io.EOF after a short read. Just read into your buffer and check the number of bytes read and the error yourself.

huangapple
  • 本文由 发表于 2014年12月11日 17:16:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/27419110.html
匿名

发表评论

匿名网友

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

确定