概要
以下、自分用のメモです。
Go の net.Listen は、バックログが指定できないんですよね。。
githubの方でもイシューとしてOpen状態となっています。
ちなみに内部でバックログとして利用される値は linux の場合は net.core.somaxconn (/proc/sys/net/core/somaxconn) の値で
存在しない場合は、 syscallパッケージのSOMAXCONN (0x80) の定数値が利用される模様。
まあ、大丈夫といえば大丈夫なのですが、やっぱり指定したいですね。
dotnetとかだと普通に引数で指定できるので。(System.Net.Sockets.TcpListener::Start(Int32))
上記の理由により、どうしてもバックログの値を設定したい場合は syscall パッケージを利用して、ソケットを直接いじります。
C言語でソケットを作るのと同じ感じですね。こんな感じ。
// listen は、指定された情報で net.Listener を生成して返します. // // Go の net.Listen は、バックログが指定できないため // テスト目的でバックログを極端に少ない状態にすることが出来ない。 // 利用される値は linux の場合は net.core.somaxconn の値であり // 存在しない場合は、 syscall.SOMAXCONN の定数値が利用される。 // // なので、バックログを指定したい場合はソケットを直接生成して // net.FileListener に紐づけて、リスナーとして利用する。 // // # REFERENCES // - https://github.com/golang/go/issues/39000 // - https://github.com/golang/go/issues/41470 // - https://github.com/valyala/tcplisten/blob/master/tcplisten.go // - https://stackoverflow.com/a/49593356 // - https://meetup-jp.toast.com/1509 func listen(addr string, backLog int) (net.Listener, error) { // make tcp addr var ( tcpAddr *net.TCPAddr err error ) tcpAddr, err = net.ResolveTCPAddr("tcp4", addr) if err != nil { return nil, err } // make socket addr var ( sockAddr syscall.SockaddrInet4 ) sockAddr.Port = tcpAddr.Port copy(sockAddr.Addr[:], tcpAddr.IP.To4()) // make socket file descriptor var ( sockFd int sockDomain = syscall.AF_INET sockType = syscall.SOCK_STREAM | syscall.SOCK_NONBLOCK | syscall.SOCK_CLOEXEC sockProto = syscall.IPPROTO_TCP ) sockFd, err = syscall.Socket(sockDomain, sockType, sockProto) if err != nil { return nil, err } // bind err = syscall.Bind(sockFd, &sockAddr) if err != nil { return nil, err } // listen err = syscall.Listen(sockFd, backLog) if err != nil { return nil, err } // make net.Listener var ( fname = fmt.Sprintf("backlog.%d.%s.%s", os.Getpid(), "tcp4", addr) file = os.NewFile(uintptr(sockFd), fname) listener net.Listener ) defer file.Close() listener, err = net.FileListener(file) if err != nil { return nil, err } return listener, nil }
参考情報
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。