golang gc竟然可以自动关闭tcp连接

疯狂的小蚂蚁go · · 1605 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

事情由来

在golang最近经常写http或者grpc服务,带着这种习惯写了tcp服务,最后看了下代码,tcp连接没有调用fd.Close()方法,竟然没有报错。是测试童鞋没有测试出来,还是另外有玄机?

来个demo模拟

服务端代码,保存为server.go

package main

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

func main() {

        addr := "0.0.0.0:8787"
        tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
        if err != nil { 
                log.Fatalf("net.ResovleTCPAddr fail:%s", addr) 
        }

        listener, err := net.ListenTCP("tcp", tcpAddr)
        if err != nil {
                log.Fatalf("listen %s fail: %s", addr, err)
        }
        log.Println("listening", addr)

        for {
                conn, err := listener.Accept()
                if err != nil {
                        log.Println("listener.Accept error:", err)
                        continue
                }
                fmt.Printf("%p\n", conn)
        }
}

客户端代码,保存为client.go

package main

import (
    "fmt"
    "net"
    "os"
)

func main() {

    for i := 0; i < 1000; i++ {
        conn, err := net.Dial("tcp", "127.0.0.1:8787")
        if err != nil {
            fmt.Println("dial failed:", err)
            os.Exit(1)
        }
        conn.Close()
    }
}

开始模拟

go run server.go
go run client.go
lsof -i:8787 #观察当前tcp状态,肯定是一堆close wait
# 等待1-2分钟
lsof -i:8787 #观察当前tcp状态,应该没有close wait

原因

通过参考https://studygolang.com/articles/7680 文章得知
,net/fd_unix.go文件里面setAddr调用了runtime.SetFinalizer方法,该方法,就是在对象没有引用时,调用netFD传的回调函数(*netFD).Close,现在明朗了。就是gc可以关闭tcp连接的

func (fd *netFD) setAddr(laddr, raddr Addr) { 
        fd.laddr = laddr
        fd.raddr = raddr
        runtime.SetFinalizer(fd, (*netFD).Close)
}


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:疯狂的小蚂蚁go

查看原文:golang gc竟然可以自动关闭tcp连接

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1605 次点击  
加入收藏 微博
1 回复  |  直到 2020-07-16 13:55:05
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传