How can i interrupt a goroutine executing (*TCPListener) Accept?

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

How can i interrupt a goroutine executing (*TCPListener) Accept?

问题

我最近在玩Go,并尝试创建一个能够在TCP连接上响应客户端的服务器。

我的问题是,如何优雅地关闭服务器并中断当前在以下调用中“阻塞”的Go协程:

func (*TCPListener) Accept

根据Accept的文档

Accept实现了Listener接口中的Accept方法;它等待下一个调用并返回一个通用的Conn。

关于错误的文档也非常稀缺。

英文:

I am playing with go lately and trying to make some server which responds to clients on a tcp connection.

My question is how do i cleanly shutdown the server and interrupt the go-routine which is currently "blocked" in the following call

> func (*TCPListener) Accept?

According to the documentation of Accept

> Accept implements the Accept method in the Listener interface; it waits for the next call and returns a generic Conn.

The errors are also very scarcely documented.

答案1

得分: 5

只需关闭从net.Listen(...)调用中获取的net.Listener并从执行的goroutine中返回。

英文:

Simply Close() the net.Listener you get from the net.Listen(...) call and return from the executing goroutine.

答案2

得分: 5

TCPListener截止时间

您不一定需要额外的goroutine(用于持续接受连接),只需指定一个Deadline(截止时间)。

例如:

for {
    // 检查是否有人想要中断接受连接
    select {
    case <-someoneWantsToEndMe:
        return // 执行 "defer listener.Close()"
    default:
        // 无事可做
    }

    // 设置截止时间并接受连接
    listener.SetDeadline(time.Now().Add(1 * time.Second))
    conn, err := listener.Accept()
    if err != nil {
        // TODO: 可以进行一些错误检查(确保是超时错误),但为了简洁起见
        continue
    }

    go handleConnection(conn)
}

以上是一个示例代码,通过设置截止时间来控制listener的接受连接操作。在每次循环中,首先检查是否有其他地方要求中断接受连接的操作,如果有,则返回并关闭listener。然后,设置截止时间并尝试接受连接,如果超时或出现其他错误,则继续下一次循环。如果成功接受连接,则使用go关键字启动一个新的goroutine来处理连接。

英文:

TCPListener Deadline

You don't necessarily need an extra go routine (that keeps accepting), simply specify a Deadline.

for example:

for {

    // Check if someone wants to interrupt accepting
    select {
    case &lt;- someoneWantsToEndMe: 
        return // runs into &quot;defer listener.Close()&quot;
    default: // nothing to do
    }

    // Accept with Deadline
    listener.SetDeadline(time.Now().Add(1 * time.Second)
    conn, err := listener.Accept()
    if err != nil {
        // TODO: Could do some err checking (to be sure it is a timeout), but for brevity
        continue
    }

    go handleConnection(conn)
}

答案3

得分: 3

这是我正在寻找的内容。也许对将来的某个人有帮助。
请注意使用select和"c"通道将其与退出通道组合的方法。

ln, err := net.Listen("tcp", ":8080")
if err != nil {
// 处理错误
}
defer ln.Close()
for {
type accepted struct {
conn net.Conn
err error
}
c := make(chan accepted, 1)
go func() {
conn, err := ln.Accept()
c <- accepted{conn, err}
}()
select {
case a := <-c:
if a.err != nil {
// 处理错误
continue
}
go handleConnection(a.conn)
case e := <-ev:
// 处理事件
return
}
}

英文:

Here is what i was looking for. Maybe helps someone in the future.
Notice the use of select and the "c" channel to combine it with the exit channel

	ln, err := net.Listen(&quot;tcp&quot;, &quot;:8080&quot;)
	if err != nil {
		// handle error
	}
	defer ln.Close()
	for {
		type accepted struct {
			conn net.Conn
			err  error
		}
		c := make(chan accepted, 1)
		go func() {
			conn, err := ln.Accept()
			c &lt;- accepted{conn, err}
		}()
		select {
		case a := &lt;-c:
			if a.err != nil {
				// handle error
				continue
			}
			go handleConnection(a.conn)
		case e := &lt;-ev:
			// handle event
			return
		}
	}

huangapple
  • 本文由 发表于 2013年9月16日 17:59:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/18825207.html
匿名

发表评论

匿名网友

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

确定