github.com/cloudwego/kitex@v0.9.0/pkg/remote/trans/listen_config.go (about)

     1  //go:build !windows
     2  // +build !windows
     3  
     4  /*
     5   * Copyright 2022 CloudWeGo Authors
     6   *
     7   * Licensed under the Apache License, Version 2.0 (the "License");
     8   * you may not use this file except in compliance with the License.
     9   * You may obtain a copy of the License at
    10   *
    11   *     http://www.apache.org/licenses/LICENSE-2.0
    12   *
    13   * Unless required by applicable law or agreed to in writing, software
    14   * distributed under the License is distributed on an "AS IS" BASIS,
    15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    16   * See the License for the specific language governing permissions and
    17   * limitations under the License.
    18   */
    19  
    20  package trans
    21  
    22  import (
    23  	"net"
    24  	"syscall"
    25  
    26  	"golang.org/x/sys/unix"
    27  
    28  	"github.com/cloudwego/kitex/pkg/remote"
    29  )
    30  
    31  // NewListenConfig return an new net.ListenConfig.
    32  func NewListenConfig(opt *remote.ServerOption) net.ListenConfig {
    33  	return net.ListenConfig{
    34  		Control: func(network, address string, c syscall.RawConn) error {
    35  			var err error
    36  			c.Control(func(fd uintptr) {
    37  				if !opt.ReusePort {
    38  					return
    39  				}
    40  				/* The real behavior of 'SO_REUSEADDR/SO_REUSEPORT' depends on the underlying OS.
    41  				For BSD(/Darwin):
    42  					With 'SO_REUSEADDR' option, the socket can be successfully bound unless there is
    43  					a conflict with another socket bound to exactly the same combination of source address and port.
    44  
    45  					Here is an example to give a better overview:
    46  					SO_REUSEADDR       socketA        socketB       Result
    47  					---------------------------------------------------------------------
    48  					  ON/OFF       192.168.0.1:21   192.168.0.1:21    Error (EADDRINUSE)
    49  					  ON/OFF       192.168.0.1:21      10.0.0.1:21    OK
    50  					  ON/OFF          10.0.0.1:21   192.168.0.1:21    OK
    51  					   OFF             0.0.0.0:21   192.168.1.0:21    Error (EADDRINUSE)
    52  					   OFF         192.168.1.0:21       0.0.0.0:21    Error (EADDRINUSE)
    53  					   ON              0.0.0.0:21   192.168.1.0:21    OK
    54  					   ON          192.168.1.0:21       0.0.0.0:21    OK
    55  					  ON/OFF           0.0.0.0:21       0.0.0.0:21    Error (EADDRINUSE)
    56  
    57  					With 'SO_REUSEPORT', you could bind an arbitrary number of sockets to exactly the same source address
    58  					and port as long as all prior bound sockets also had 'SO_REUSEPORT' set before they were bound.
    59  				For Linux < 3.9:
    60  					Only the option 'SO_REUSEADDR' existed.
    61  				For Linux >= 3.9:
    62  					The 'SO_REUSEPORT' behaves exactly like the option in BSD.
    63  
    64  				More details can be found at https://stackoverflow.com/questions/14388706/how-do-so-reuseaddr-and-so-reuseport-differ.
    65  				*/
    66  				if err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1); err != nil {
    67  					return
    68  				}
    69  				if err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
    70  					return
    71  				}
    72  			})
    73  			return err
    74  		},
    75  	}
    76  }