如何优雅的关闭net.Listeners

使用golang做网络应用时,创建网络服务器时需要用到net.Listeners生成一个监听器,阻塞处理连接到服务器的请求,如下所示:

func main(){
    ln, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", 1234))
    if err != nil {
        log.Fatal(err)
    }
    log.Println("server start...")
    for {
        conn, err := ln.Accept()
        if err != nil {
            log.Fatal(err)
        }
        handle(conn)
    }
}

但是ln.Accept()是一个阻塞函数,我们无法在某时刻通知并令其退出(处于一个for循环之中),并且有时我们需要在关闭监听器之后做一些收尾或清理的操作。对于一个常驻进程,只能通过杀进程的方式结束,无法满足这些需求,确实不是一个优雅的处理方式。
在这里我们使用channel的思想来解决这一问题,具体实现如下:

package main

import (
    "fmt"
    "log"
    "net"
    "time"
)

var (
    quit = make(chan struct{})
    ln   net.Listener
)

func main() {

    ln, err := net.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", 1234))
    if err != nil {
        log.Fatal(err)
    }
    go start()
    time.Sleep(1 * time.Second)
    stop()
    time.Sleep(1 * time.Second)
}

func start() {
    log.Println("server start...")
    for {
        conn, err := ln.Accept()
        if err != nil {
            select {
            default:
            case <-quit:
                //do something
                return
            }
            fmt.Println(err)
        }
        handle(conn)
    }
}
func stop() {
    close(quit)
    ln.Close()
}

//handle connection
func handle(conn net.Conn) {
    //......
}

增加了一个叫quit的channel,当我们关闭listener的时候也关闭此channel,监听器报错以后检测到quit已经关闭可以做一些后续处理然后再返回,达到了优雅退出的效果。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • SIGINT SIGTERM SIGKILL区别 三者都是结束/终止进程运行。 1.SIGINT SIGTERM区...
    go4it阅读 4,818评论 0 3
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,841评论 18 139
  • daemon: Linux Daemon(守护进程)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某...
    烨哥阅读 3,588评论 0 6
  • 什么是Nginx? Nginx是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器N...
    jiangmo阅读 2,577评论 1 9
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 172,896评论 25 708