Golang笔记

Golang http IPv4/IPv6 服务

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

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

# 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 来选择,如:

http.ListenAndServe(":8083", nil)  // tcp
http.ListenAndServe("[2604:180:3:dd3::276e]:8083", nil) // 具体指定 tcp6

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

network 可选参数:

"tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only), "udp", "udp4" (IPv4-only), "udp6" (IPv6-only), "ip", "ip4" (IPv4-only), "ip6" (IPv6-only), "unix", "unixgram" and "unixpacket"

常用:

tcp     自动适配,优先IPv6
tcp4    仅使用IPv4
tcp6    仅使用IPv6

重构的 ListenAndServe 函数示例:

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 服务:

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 (转载注明出处)
关于GolangNote:记录在工作中使用golang 遇到、面临的相关问题及解决方法。如果你在这里获得一些知识或信息,解决你的编程问题,请考虑捐赠给不幸的人或者你喜欢的慈善机构,除捐赠外,种植树木、志愿服务或减少排碳的行为也很有益处。如果你有任何问题可以在下面 留言
Be the first to comment!
Captcha image
Relative Articles