如何停止Go中的Listening服务器 [英] How do I stop a Listening server in Go

查看:216
本文介绍了如何停止Go中的Listening服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在试图找到一种方法来优雅地停止Go中的侦听服务器。由于 listen.Accept 阻塞,因此有必要关闭监听套接字来告知结束,但除了其他错误之外,我无法确定该错误,因为相关错误不是' t出口。



我能做得更好吗?在 serve()



<$的代码中见 FIXME
io
log
net
time


//回声服务器结构
类型EchoServer结构{
监听net.Listener
完成chan bool
}

//响应传入连接
//
//写入连接的地址echo
func(es * EchoServer)respond(remote * net.TCPConn){
defer remote.Close()
_,err:= io.Copy(remote,remote)
if err!= nil {
log.Printf(Error:%s, err)



//监听传入连接
func(es * EchoServer)serve(){
for {
conn,err:= es.listen.Accept()
// FIXME我想在这里检测使用封闭网络连接
// FIXME,但它不会从net $ b导出$ b if err!= nil {
log.Printf(Accept failed:%v,err)
break

去es.respond(conn。(* net.TCPConn))
}
es.done< - true
}

//关闭监听来停止服务器
func(es * EchoServer)stop(){
es.listen.Close()
<-es。完成

$ b $ //创建一个新的回显服务器
func NewEchoServer(地址字符串)* EchoServer {
listen,err:= net.Listen(tcp ,地址)
if err!= nil {
log.Fatalf(无法打开监听套接字:%s,err)
}
es:=& EchoServer {
listen:listen,
done:make(chan bool),
}
go es.serve()
return es
}

// Main
func main(){
log.Println(Starting echo server)
es:= NewEchoServer(127.0.0.1:18081)
//运行服务器1秒
time.Sleep(1 * time.Second)
//关闭服务器
log.Println(停止echo服务器)
es.stop()
}

打印

  2012/11/16 12:53:35启动回显服务器
2012/11/16 12:53:36停止回显服务器
2012/11/16 12:53:36接受失败:接受TCP 127.0.0.1:18081:使用封闭的网络连接

我想隐藏接受失败消息,但显然我不想掩盖其他错误接受可以报告。我当然可以看看使用封闭网络连接的错误测试,但那会非常难看。我可以设置一个标志,说我即将关闭并忽略错误,如果设置了,我想 - 有没有更好的方法?

解决方案

accept()调用之后,检查循环中的一些是时候停止标志,然后将它从 main ,然后将 connect 连接到您的监听端口,以使服务器套接字未卡住。这与旧的自我推销技巧非常相似。


I've been trying to find a way to stop a listening server in Go gracefully. Because listen.Accept blocks it is necessary to close the listening socket to signal the end, but I can't tell that error apart from any other errors as the relevant error isn't exported.

Can I do better than this? See FIXME in the code below in serve()

package main

import (
    "io"
    "log"
    "net"
    "time"
)

// Echo server struct
type EchoServer struct {
    listen net.Listener
    done   chan bool
}

// Respond to incoming connection
//
// Write the address connected to then echo
func (es *EchoServer) respond(remote *net.TCPConn) {
    defer remote.Close()
    _, err := io.Copy(remote, remote)
    if err != nil {
        log.Printf("Error: %s", err)
    }
}

// Listen for incoming connections
func (es *EchoServer) serve() {
    for {
        conn, err := es.listen.Accept()
        // FIXME I'd like to detect "use of closed network connection" here
        // FIXME but it isn't exported from net
        if err != nil {
            log.Printf("Accept failed: %v", err)
            break
        }
        go es.respond(conn.(*net.TCPConn))
    }
    es.done <- true
}

// Stop the server by closing the listening listen
func (es *EchoServer) stop() {
    es.listen.Close()
    <-es.done
}

// Make a new echo server
func NewEchoServer(address string) *EchoServer {
    listen, err := net.Listen("tcp", address)
    if err != nil {
        log.Fatalf("Failed to open listening socket: %s", err)
    }
    es := &EchoServer{
        listen: listen,
        done:   make(chan bool),
    }
    go es.serve()
    return es
}

// Main
func main() {
    log.Println("Starting echo server")
    es := NewEchoServer("127.0.0.1:18081")
    // Run the server for 1 second
    time.Sleep(1 * time.Second)
    // Close the server
    log.Println("Stopping echo server")
    es.stop()
}

This prints

2012/11/16 12:53:35 Starting echo server
2012/11/16 12:53:36 Stopping echo server
2012/11/16 12:53:36 Accept failed: accept tcp 127.0.0.1:18081: use of closed network connection

I'd like to hide the Accept failed message, but obviously I don't want to mask other errors Accept can report. I could of course look in the error test for use of closed network connection but that would be really ugly. I could set a flag saying I'm about to close and ignore errors if that was set I suppose - Is there a better way?

解决方案

Check some "is it time to stop" flag in your loop right after the accept() call, then flip it from your main, then connect to your listening port to get server socket "un-stuck". This is very similar to the old "self-pipe trick".

这篇关于如何停止Go中的Listening服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆