英文:
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 <- someoneWantsToEndMe:
return // runs into "defer listener.Close()"
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("tcp", ":8080")
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 <- accepted{conn, err}
}()
select {
case a := <-c:
if a.err != nil {
// handle error
continue
}
go handleConnection(a.conn)
case e := <-ev:
// handle event
return
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论