使用Go语言创建多进程共享端口监听
发表时间: 2024-05-20 17:41
HTTP 多进程监听一个端口
常见的问题: listen tcp :8000: bind: address already in use
方式一
package mainimport ( "context" "fmt" "net" "net/http" "os" "syscall" "golang.org/x/sys/unix" // unix 包 不支持 window 操作系统)var lc = net.ListenConfig{Control: func(network, address string, c syscall.RawConn) error {var opErr errorif err := c.Control(func(fd uintptr) { opErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1) }); err != nil { return err } return opErr },}func main() { pid := os.Getpid() // 绑定监听端口 l, err := lc.Listen(context.Background(), "tcp", "127.0.0.1:8000") if err != nil { panic(err) } server := &http.Server{} http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) fmt.Fprintf(w, "客户端 Client [%s] Received msg from Server PID: [%d] \n", r.RemoteAddr, pid) }) fmt.Printf("服务端 Server with PID: [%d] is running \n", pid) _ = server.Serve(l)}
> # go run http.goServer with PID: [56730] is running> # go run http.goServer with PID: [57172] is running
方式二:
package mainimport ( "context" "fmt" "net" "net/http" "os" "syscall" "github.com/sirupsen/logrus" "golang.org/x/sys/unix")type TestHandler struct { RESP []byte}func (handler *TestHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) { resp.WriteHeader(200) resp.Write(handler.RESP)}func Control(network, address string, c syscall.RawConn) error { var err error c.Control(func(fd uintptr) { err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1) if err != nil { logrus.Error("Failed to set sock SO_REUSEADDR. ", err) return } err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1) if err != nil { logrus.Error("Failed to set sock SO_REUSEPORT. ", err) return } }) return err}func main() { // 获取进程id号 pid := os.Getpid() lc := &net.ListenConfig{ Control: Control, } // 第二个参数必须是"tcp"、"tcp4"、"tcp6", 一般使用tcp, 兼容tcp4 和 tcp6 ln, err := lc.Listen(context.Background(), "tcp", "127.0.0.1:8000") if err != nil { logrus.Panic("Failed to listen. ", err) } fmt.Printf("Server with PID: [%d] is running \n", pid) err = http.Serve(ln, &TestHandler{ RESP: []byte("127.0.0.1:8000"), }) if err != nil { logrus.Panic("Failed to listen. ", err) }}
> # go run http.goServer with PID: [76512] is running> # go run http.goServer with PID: [76632] is running
注意: 以上代码只能运行在 Linux 平台下;
window 平台下支持 一个端口 创建 libp2p服务和一个HTTP服务 监听一个端口号;