如何知道 net.Listener 是否已经正确关闭?

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

How to know when the net.Listener was properly closed?

问题

我有以下的代码:

server := &http.Server{Addr: addr, Handler: r}

l, err := net.Listen("tcp", addr)
if err != nil {
	logging.Error("Failed opening socket: %s", err)
}

if err := server.Serve(l); err != nil {
    // error handling
}

当调用l.Close()时,server.Serve(l)将会以一个错误退出。我想知道这是否真的是一个错误,还是只是因为有人调用了l.Close()(对我来说不是错误)的结果。

有没有一种合适的方法来做到这一点?

英文:

I have the following code:

server := &http.Server{Addr: addr, Handler: r}

l, err := net.Listen("tcp", addr)
if err != nil {
	logging.Error("Failed opening socket: %s", err)
}

if err := server.Serve(l); err != nil {
    // error handling
}

When l.Close() is called, server.Serve(l) will exit with an error. I would like to know whether this is truly an error or just the result of someone calling l.Close() (which is non error for me).

Is there a proper way to do this?

答案1

得分: 1

一些关于TCP套接字的hack-ish方法:

read_len, err := conn.Read(request)

if err != nil {

  if err.Error() == "use of closed network connection" { 
    // 当套接字关闭时做一些操作
    break
  }

if err := server.Serve(l); err != nil {下尝试使用if err.Error() == "use of closed network connection",或者在你的TCP处理函数中使用。

英文:

Some hack-ish way about TCP socket:

read_len, err := conn.Read(request)

if err != nil {

  if err.Error() == "use of closed network connection" { 
    // Do something when socket closed
    break
  }

Try if err.Error() == "use of closed network connection" under if err := server.Serve(l); err != nil {, or in your TCP handler function.

答案2

得分: 0

使用实现io.ReadWriteCloser接口的接口,通常会返回io.EOFio.ErrUnexpectedEOF错误。net.Listener实现了io.Closer,所以我期望它也会返回这个错误,但不幸的是它没有遵循这个约定。相反,它返回了一个私有声明的errClosing in net.go

net.Listener返回的错误被包装在net.OpError中。这个结构体有一些额外的信息可能会有帮助 - 特别是“Op”和“Err”。“Op”告诉你错误发生的位置。当你执行Close() error时,你会得到“accept”。文档还说你也可以得到“read”和“write”。

要获取net.OpError,你可以这样做:

err := server.Serve(l)
if opErr, ok := err.(*net.OpError); ok {
    // opErr.Op, opErr.Err, ...
}

或者像这样(假设net.Listener总是返回一个net.OpError):

err := server.Serve(l).(*net.OpError)

net.OptError.Err返回原始错误,这可能会有帮助,如果错误被导出。无论如何,我不建议检查字符串,因为这在将来的版本中可能会出问题。最好直接将错误与导出的错误进行比较,而你没有。

net.OptError还声明了一个Temporary() bool函数。net/http使用这个函数在递增的时间间隔上重新建立连接。所以在net/http的情况下,我会假设返回的任何错误都是调用Close() error的结果。否则,Temporary() bool会返回true,net/http会为你捕获。

英文:

With interfaces that implement io.ReadWriteCloser you typically get back an io.EOF and io.ErrUnexpectedEOF error. net.Listener implements io.Closer, so I would expect it to also return this error, but it unfortunately does not follow this convention. Instead, it returns a privately declared errClosing in net.go.

Errors returned by net.Listener are wrapped in net.OpError. This struct has some additional information that may be helpful - specifically "Op" and "Err". "Op" tells you where the error occurred. When you execute Close() error you get "accept" back. The documentation says you can also get "read" and "write" back.

To get net.OpError, you can do this:

err := server.Serve(l)
if opErr, ok := err.(*net.OpError); ok {
    // opErr.Op, opErr.Err, ...
}

Or like this (assuming that net.Listener always returns a net.OpError):

err := server.Serve(l).(*net.OpError)

net.OptError.Err returns the original error, which would be helpful if the error was exported. Either way I don't recommend checking the string as that could break in future versions. It's better to compare the error directly to the exported error, which you don't have.

net.OptError also has a Temporary() bool function declared. The net/http package uses this to re-establish the connection on a increasing interval. So in the case of net/http I would assume that any error that returns would be a result of calling Close() error. Otherwise Temporary() bool would return true, which net/http catches for you.

huangapple
  • 本文由 发表于 2013年5月23日 02:33:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/16699182.html
匿名

发表评论

匿名网友

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

确定