GolangNote

Golang笔记

Golang http IPv4/IPv6 服务

Permalink

Golang 的网络服务,如果不指定IPv4 或 IPv6,如果VPS 同时支持 IPv4 和 IPv6,net.Listen() 只会监听 IPv6 地址。但这不影响客户端使用 IPv4 地址来访问。

如下使用 netstat -lnt 来查看端口监听情况:

Bash: netstat 查看端口监听
1
2
3
4
5
6
7
8
9
10
11
# netstat -lnt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:25              0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN     
tcp6       0      0 :::22                   :::*                    LISTEN     
tcp6       0      0 :::25                   :::*                    LISTEN     
tcp6       0      0 :::443                  :::*                    LISTEN     
tcp6       0      0 :::111                  :::*                    LISTEN     
tcp6       0      0 :::80                   :::*                    LISTEN

IPv6

如何在启动网络服务时选择 IPv6?

在高层可以使用 http.ListenAndServe 来选择,如:

Go: 启动网络服务时具体指定 tcp6
1
2
3
http.ListenAndServe(":8083", nil)  // tcp
http.ListenAndServe("[2604:180:3:dd3::276e]:8083", nil) // 具体指定 tcp6

如果觉得具体指定 IPv6地址太麻烦,可以重构 ListenAndServe 函数,会用到 net.Listen 函数, 可以在该函数里指定 network ,可选 tcptcp4tcp6

network 可选参数:

plaintext: network 可选参数
1
2
3
4
5
6
7
8
9
10
11
12
"tcp", 
"tcp4" (IPv4-only), 
"tcp6" (IPv6-only), 
"udp", 
"udp4" (IPv4-only), 
"udp6" (IPv6-only), 
"ip", 
"ip4" (IPv4-only), 
"ip6" (IPv6-only), 
"unix", 
"unixgram", 
"unixpacket",

常用:

plaintext: 常用 tcp 参数
1
2
3
tcp     自动适配,优先IPv6
tcp4    仅使用IPv4
tcp6    仅使用IPv6

重构的 ListenAndServe 函数示例:

Go: 重构 ListenAndServe 函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package main

import (
    "fmt"
    "net"
    "net/http"
)

type helloHandler struct{}

func (h *helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello, world!"))
}

func main() {
    var err error
    http.Handle("/", &helloHandler{})
    //err = http.ListenAndServe(":8083", nil) // IPv4 或 IPv6
    //err = http.ListenAndServe("[2604:180:3:dd3::276e]:8083", nil) // 具体指定,仅 IPv6
    err = ListenAndServe(":8083", nil) // 重构的 ListenAndServe 函数
    if err != nil {
        fmt.Println(err)
    }

}

//
type tcpKeepAliveListener struct {
    *net.TCPListener
}

func ListenAndServe(addr string, handler http.Handler) error {
    srv := &http.Server{Addr: addr, Handler: handler}
    addr = srv.Addr
    if addr == "" {
        addr = ":http"
    }
    ln, err := net.Listen("tcp6", addr) // 仅指定 IPv6
    if err != nil {
        return err
    }
    return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
}

客户端可以用下面的命令行检测 IPv6 服务:

Bash: 检测 IPv6 服务
1
2
3
curl "http://[2604:180:3:dd3::276e]:8083"
curl -g -6 'http://[2604:180:3:dd3::276e]:8083/'
telnet -6 2604:180:3:dd3::276e 8083

本文网址: https://golangnote.com/topic/256.html 转摘请注明来源

Related articles

Write a Comment to "Golang http IPv4/IPv6 服务"

Submit Comment Login
Based on Golang + fastHTTP + sdb | go1.17 Processed in 1ms