Source File
dial.go
Belonging Package
net
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package net
import (
)
const (
// defaultTCPKeepAliveIdle is a default constant value for TCP_KEEPIDLE.
// See go.dev/issue/31510 for details.
defaultTCPKeepAliveIdle = 15 * time.Second
// defaultTCPKeepAliveInterval is a default constant value for TCP_KEEPINTVL.
// It is the same as defaultTCPKeepAliveIdle, see go.dev/issue/31510 for details.
defaultTCPKeepAliveInterval = 15 * time.Second
// defaultTCPKeepAliveCount is a default constant value for TCP_KEEPCNT.
defaultTCPKeepAliveCount = 9
// For the moment, MultiPath TCP is used by default with listeners, if
// available, but not with dialers.
// See go.dev/issue/56539
defaultMPTCPEnabledListen = true
defaultMPTCPEnabledDial = false
)
// The type of service offered
//
// 0 == MPTCP disabled
// 1 == MPTCP enabled
// 2 == MPTCP enabled on listeners only
// 3 == MPTCP enabled on dialers only
var multipathtcp = godebug.New("multipathtcp")
// mptcpStatusDial is a tristate for Multipath TCP on clients,
// see go.dev/issue/56539
type mptcpStatusDial uint8
const (
// The value 0 is the system default, linked to defaultMPTCPEnabledDial
mptcpUseDefaultDial mptcpStatusDial = iota
mptcpEnabledDial
mptcpDisabledDial
)
func ( *mptcpStatusDial) () bool {
switch * {
case mptcpEnabledDial:
return true
case mptcpDisabledDial:
return false
}
// If MPTCP is forced via GODEBUG=multipathtcp=1
if multipathtcp.Value() == "1" || multipathtcp.Value() == "3" {
multipathtcp.IncNonDefault()
return true
}
return defaultMPTCPEnabledDial
}
func ( *mptcpStatusDial) ( bool) {
if {
* = mptcpEnabledDial
} else {
* = mptcpDisabledDial
}
}
// mptcpStatusListen is a tristate for Multipath TCP on servers,
// see go.dev/issue/56539
type mptcpStatusListen uint8
const (
// The value 0 is the system default, linked to defaultMPTCPEnabledListen
mptcpUseDefaultListen mptcpStatusListen = iota
mptcpEnabledListen
mptcpDisabledListen
)
func ( *mptcpStatusListen) () bool {
switch * {
case mptcpEnabledListen:
return true
case mptcpDisabledListen:
return false
}
// If MPTCP is disabled via GODEBUG=multipathtcp=0 or only
// enabled on dialers, but not on listeners.
if multipathtcp.Value() == "0" || multipathtcp.Value() == "3" {
multipathtcp.IncNonDefault()
return false
}
return defaultMPTCPEnabledListen
}
func ( *mptcpStatusListen) ( bool) {
if {
* = mptcpEnabledListen
} else {
* = mptcpDisabledListen
}
}
// A Dialer contains options for connecting to an address.
//
// The zero value for each field is equivalent to dialing
// without that option. Dialing with the zero value of Dialer
// is therefore equivalent to just calling the [Dial] function.
//
// It is safe to call Dialer's methods concurrently.
type Dialer struct {
// Timeout is the maximum amount of time a dial will wait for
// a connect to complete. If Deadline is also set, it may fail
// earlier.
//
// The default is no timeout.
//
// When using TCP and dialing a host name with multiple IP
// addresses, the timeout may be divided between them.
//
// With or without a timeout, the operating system may impose
// its own earlier timeout. For instance, TCP timeouts are
// often around 3 minutes.
Timeout time.Duration
// Deadline is the absolute point in time after which dials
// will fail. If Timeout is set, it may fail earlier.
// Zero means no deadline, or dependent on the operating system
// as with the Timeout option.
Deadline time.Time
// LocalAddr is the local address to use when dialing an
// address. The address must be of a compatible type for the
// network being dialed.
// If nil, a local address is automatically chosen.
LocalAddr Addr
// DualStack previously enabled RFC 6555 Fast Fallback
// support, also known as "Happy Eyeballs", in which IPv4 is
// tried soon if IPv6 appears to be misconfigured and
// hanging.
//
// Deprecated: Fast Fallback is enabled by default. To
// disable, set FallbackDelay to a negative value.
DualStack bool
// FallbackDelay specifies the length of time to wait before
// spawning a RFC 6555 Fast Fallback connection. That is, this
// is the amount of time to wait for IPv6 to succeed before
// assuming that IPv6 is misconfigured and falling back to
// IPv4.
//
// If zero, a default delay of 300ms is used.
// A negative value disables Fast Fallback support.
FallbackDelay time.Duration
// KeepAlive specifies the interval between keep-alive
// probes for an active network connection.
//
// KeepAlive is ignored if KeepAliveConfig.Enable is true.
//
// If zero, keep-alive probes are sent with a default value
// (currently 15 seconds), if supported by the protocol and operating
// system. Network protocols or operating systems that do
// not support keep-alive ignore this field.
// If negative, keep-alive probes are disabled.
KeepAlive time.Duration
// KeepAliveConfig specifies the keep-alive probe configuration
// for an active network connection, when supported by the
// protocol and operating system.
//
// If KeepAliveConfig.Enable is true, keep-alive probes are enabled.
// If KeepAliveConfig.Enable is false and KeepAlive is negative,
// keep-alive probes are disabled.
KeepAliveConfig KeepAliveConfig
// Resolver optionally specifies an alternate resolver to use.
Resolver *Resolver
// Cancel is an optional channel whose closure indicates that
// the dial should be canceled. Not all types of dials support
// cancellation.
//
// Deprecated: Use DialContext instead.
Cancel <-chan struct{}
// If Control is not nil, it is called after creating the network
// connection but before actually dialing.
//
// Network and address parameters passed to Control function are not
// necessarily the ones passed to Dial. Calling Dial with TCP networks
// will cause the Control function to be called with "tcp4" or "tcp6",
// UDP networks become "udp4" or "udp6", IP networks become "ip4" or "ip6",
// and other known networks are passed as-is.
//
// Control is ignored if ControlContext is not nil.
Control func(network, address string, c syscall.RawConn) error
// If ControlContext is not nil, it is called after creating the network
// connection but before actually dialing.
//
// Network and address parameters passed to ControlContext function are not
// necessarily the ones passed to Dial. Calling Dial with TCP networks
// will cause the ControlContext function to be called with "tcp4" or "tcp6",
// UDP networks become "udp4" or "udp6", IP networks become "ip4" or "ip6",
// and other known networks are passed as-is.
//
// If ControlContext is not nil, Control is ignored.
ControlContext func(ctx context.Context, network, address string, c syscall.RawConn) error
// If mptcpStatus is set to a value allowing Multipath TCP (MPTCP) to be
// used, any call to Dial with "tcp(4|6)" as network will use MPTCP if
// supported by the operating system.
mptcpStatus mptcpStatusDial
}
func ( *Dialer) () bool { return .FallbackDelay >= 0 }
func minNonzeroTime(, time.Time) time.Time {
if .IsZero() {
return
}
if .IsZero() || .Before() {
return
}
return
}
// deadline returns the earliest of:
// - now+Timeout
// - d.Deadline
// - the context's deadline
//
// Or zero, if none of Timeout, Deadline, or context's deadline is set.
func ( *Dialer) ( context.Context, time.Time) ( time.Time) {
if .Timeout != 0 { // including negative, for historical reasons
= .Add(.Timeout)
}
if , := .Deadline(); {
= minNonzeroTime(, )
}
return minNonzeroTime(, .Deadline)
}
func ( *Dialer) () *Resolver {
if .Resolver != nil {
return .Resolver
}
return DefaultResolver
}
// partialDeadline returns the deadline to use for a single address,
// when multiple addresses are pending.
func partialDeadline(, time.Time, int) (time.Time, error) {
if .IsZero() {
return , nil
}
:= .Sub()
if <= 0 {
return time.Time{}, errTimeout
}
// Tentatively allocate equal time to each remaining address.
:= / time.Duration()
// If the time per address is too short, steal from the end of the list.
const = 2 * time.Second
if < {
if < {
=
} else {
=
}
}
return .Add(), nil
}
func ( *Dialer) () time.Duration {
if .FallbackDelay > 0 {
return .FallbackDelay
} else {
return 300 * time.Millisecond
}
}
func parseNetwork( context.Context, string, bool) ( string, int, error) {
:= bytealg.LastIndexByteString(, ':')
if < 0 { // no colon
switch {
case "tcp", "tcp4", "tcp6":
case "udp", "udp4", "udp6":
case "ip", "ip4", "ip6":
if {
return "", 0, UnknownNetworkError()
}
case "unix", "unixgram", "unixpacket":
default:
return "", 0, UnknownNetworkError()
}
return , 0, nil
}
= [:]
switch {
case "ip", "ip4", "ip6":
:= [+1:]
, , := dtoi()
if ! || != len() {
, = lookupProtocol(, )
if != nil {
return "", 0,
}
}
return , , nil
}
return "", 0, UnknownNetworkError()
}
// resolveAddrList resolves addr using hint and returns a list of
// addresses. The result contains at least one address when error is
// nil.
func ( *Resolver) ( context.Context, , , string, Addr) (addrList, error) {
, , := parseNetwork(, , true)
if != nil {
return nil,
}
if == "dial" && == "" {
return nil, errMissingAddress
}
switch {
case "unix", "unixgram", "unixpacket":
, := ResolveUnixAddr(, )
if != nil {
return nil,
}
if == "dial" && != nil && .Network() != .Network() {
return nil, &AddrError{Err: "mismatched local address type", Addr: .String()}
}
return addrList{}, nil
}
, := .internetAddrList(, , )
if != nil || != "dial" || == nil {
return ,
}
var (
*TCPAddr
*UDPAddr
*IPAddr
bool
)
switch hint := .(type) {
case *TCPAddr:
=
= .isWildcard()
case *UDPAddr:
=
= .isWildcard()
case *IPAddr:
=
= .isWildcard()
}
:= [:0]
for , := range {
if .Network() != .Network() {
return nil, &AddrError{Err: "mismatched local address type", Addr: .String()}
}
switch addr := .(type) {
case *TCPAddr:
if ! && !.isWildcard() && !.IP.matchAddrFamily(.IP) {
continue
}
= append(, )
case *UDPAddr:
if ! && !.isWildcard() && !.IP.matchAddrFamily(.IP) {
continue
}
= append(, )
case *IPAddr:
if ! && !.isWildcard() && !.IP.matchAddrFamily(.IP) {
continue
}
= append(, )
}
}
if len() == 0 {
return nil, &AddrError{Err: errNoSuitableAddress.Error(), Addr: .String()}
}
return , nil
}
// MultipathTCP reports whether MPTCP will be used.
//
// This method doesn't check if MPTCP is supported by the operating
// system or not.
func ( *Dialer) () bool {
return .mptcpStatus.get()
}
// SetMultipathTCP directs the [Dial] methods to use, or not use, MPTCP,
// if supported by the operating system. This method overrides the
// system default and the GODEBUG=multipathtcp=... setting if any.
//
// If MPTCP is not available on the host or not supported by the server,
// the Dial methods will fall back to TCP.
func ( *Dialer) ( bool) {
.mptcpStatus.set()
}
// Dial connects to the address on the named network.
//
// Known networks are "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".
//
// For TCP and UDP networks, the address has the form "host:port".
// The host must be a literal IP address, or a host name that can be
// resolved to IP addresses.
// The port must be a literal port number or a service name.
// If the host is a literal IPv6 address it must be enclosed in square
// brackets, as in "[2001:db8::1]:80" or "[fe80::1%zone]:80".
// The zone specifies the scope of the literal IPv6 address as defined
// in RFC 4007.
// The functions [JoinHostPort] and [SplitHostPort] manipulate a pair of
// host and port in this form.
// When using TCP, and the host resolves to multiple IP addresses,
// Dial will try each IP address in order until one succeeds.
//
// Examples:
//
// Dial("tcp", "golang.org:http")
// Dial("tcp", "192.0.2.1:http")
// Dial("tcp", "198.51.100.1:80")
// Dial("udp", "[2001:db8::1]:domain")
// Dial("udp", "[fe80::1%lo0]:53")
// Dial("tcp", ":80")
//
// For IP networks, the network must be "ip", "ip4" or "ip6" followed
// by a colon and a literal protocol number or a protocol name, and
// the address has the form "host". The host must be a literal IP
// address or a literal IPv6 address with zone.
// It depends on each operating system how the operating system
// behaves with a non-well known protocol number such as "0" or "255".
//
// Examples:
//
// Dial("ip4:1", "192.0.2.1")
// Dial("ip6:ipv6-icmp", "2001:db8::1")
// Dial("ip6:58", "fe80::1%lo0")
//
// For TCP, UDP and IP networks, if the host is empty or a literal
// unspecified IP address, as in ":80", "0.0.0.0:80" or "[::]:80" for
// TCP and UDP, "", "0.0.0.0" or "::" for IP, the local system is
// assumed.
//
// For Unix networks, the address must be a file system path.
func (, string) (Conn, error) {
var Dialer
return .Dial(, )
}
// DialTimeout acts like [Dial] but takes a timeout.
//
// The timeout includes name resolution, if required.
// When using TCP, and the host in the address parameter resolves to
// multiple IP addresses, the timeout is spread over each consecutive
// dial, such that each is given an appropriate fraction of the time
// to connect.
//
// See func Dial for a description of the network and address
// parameters.
func (, string, time.Duration) (Conn, error) {
:= Dialer{Timeout: }
return .Dial(, )
}
// sysDialer contains a Dial's parameters and configuration.
type sysDialer struct {
Dialer
network, address string
testHookDialTCP func(ctx context.Context, net string, laddr, raddr *TCPAddr) (*TCPConn, error)
}
// Dial connects to the address on the named network.
//
// See func Dial for a description of the network and address
// parameters.
//
// Dial uses [context.Background] internally; to specify the context, use
// [Dialer.DialContext].
func ( *Dialer) (, string) (Conn, error) {
return .DialContext(context.Background(), , )
}
// DialContext connects to the address on the named network using
// the provided context.
//
// The provided Context must be non-nil. If the context expires before
// the connection is complete, an error is returned. Once successfully
// connected, any expiration of the context will not affect the
// connection.
//
// When using TCP, and the host in the address parameter resolves to multiple
// network addresses, any dial timeout (from d.Timeout or ctx) is spread
// over each consecutive dial, such that each is given an appropriate
// fraction of the time to connect.
// For example, if a host has 4 IP addresses and the timeout is 1 minute,
// the connect to each single address will be given 15 seconds to complete
// before trying the next one.
//
// See func [Dial] for a description of the network and address
// parameters.
func ( *Dialer) ( context.Context, , string) (Conn, error) {
if == nil {
panic("nil context")
}
:= .deadline(, time.Now())
if !.IsZero() {
testHookStepTime()
if , := .Deadline(); ! || .Before() {
, := context.WithDeadline(, )
defer ()
=
}
}
if := .Cancel; != nil {
, := context.WithCancel()
defer ()
go func() {
select {
case <-:
()
case <-.Done():
}
}()
=
}
// Shadow the nettrace (if any) during resolve so Connect events don't fire for DNS lookups.
:=
if , := .Value(nettrace.TraceKey{}).(*nettrace.Trace); != nil {
:= *
.ConnectStart = nil
.ConnectDone = nil
= context.WithValue(, nettrace.TraceKey{}, &)
}
, := .resolver().resolveAddrList(, "dial", , , .LocalAddr)
if != nil {
return nil, &OpError{Op: "dial", Net: , Source: nil, Addr: nil, Err: }
}
:= &sysDialer{
Dialer: *,
network: ,
address: ,
}
var , addrList
if .dualStack() && == "tcp" {
, = .partition(isIPv4)
} else {
=
}
return .dialParallel(, , )
}
// dialParallel races two copies of dialSerial, giving the first a
// head start. It returns the first established connection and
// closes the others. Otherwise it returns an error from the first
// primary address.
func ( *sysDialer) ( context.Context, , addrList) (Conn, error) {
if len() == 0 {
return .dialSerial(, )
}
:= make(chan struct{})
defer close()
type struct {
Conn
error
bool
bool
}
:= make(chan ) // unbuffered
:= func( context.Context, bool) {
:=
if ! {
=
}
, := .dialSerial(, )
select {
case <- {: , : , : , : true}:
case <-:
if != nil {
.Close()
}
}
}
var ,
// Start the main racer.
, := context.WithCancel()
defer ()
go (, true)
// Start the timer for the fallback racer.
:= time.NewTimer(.fallbackDelay())
defer .Stop()
for {
select {
case <-.C:
, := context.WithCancel()
defer ()
go (, false)
case := <-:
if . == nil {
return ., nil
}
if . {
=
} else {
=
}
if . && . {
return nil, .
}
if . && .Stop() {
// If we were able to stop the timer, that means it
// was running (hadn't yet started the fallback), but
// we just got an error on the primary path, so start
// the fallback immediately (in 0 nanoseconds).
.Reset(0)
}
}
}
}
// dialSerial connects to a list of addresses in sequence, returning
// either the first successful connection, or the first error.
func ( *sysDialer) ( context.Context, addrList) (Conn, error) {
var error // The error from the first address is most relevant.
for , := range {
select {
case <-.Done():
return nil, &OpError{Op: "dial", Net: .network, Source: .LocalAddr, Addr: , Err: mapErr(.Err())}
default:
}
:=
if , := .Deadline(); {
, := partialDeadline(time.Now(), , len()-)
if != nil {
// Ran out of time.
if == nil {
= &OpError{Op: "dial", Net: .network, Source: .LocalAddr, Addr: , Err: }
}
break
}
if .Before() {
var context.CancelFunc
, = context.WithDeadline(, )
defer ()
}
}
, := .dialSingle(, )
if == nil {
return , nil
}
if == nil {
=
}
}
if == nil {
= &OpError{Op: "dial", Net: .network, Source: nil, Addr: nil, Err: errMissingAddress}
}
return nil,
}
// dialSingle attempts to establish and returns a single connection to
// the destination address.
func ( *sysDialer) ( context.Context, Addr) ( Conn, error) {
, := .Value(nettrace.TraceKey{}).(*nettrace.Trace)
if != nil {
:= .String()
if .ConnectStart != nil {
.ConnectStart(.network, )
}
if .ConnectDone != nil {
defer func() { .ConnectDone(.network, , ) }()
}
}
:= .LocalAddr
switch ra := .(type) {
case *TCPAddr:
, := .(*TCPAddr)
if .MultipathTCP() {
, = .dialMPTCP(, , )
} else {
, = .dialTCP(, , )
}
case *UDPAddr:
, := .(*UDPAddr)
, = .dialUDP(, , )
case *IPAddr:
, := .(*IPAddr)
, = .dialIP(, , )
case *UnixAddr:
, := .(*UnixAddr)
, = .dialUnix(, , )
default:
return nil, &OpError{Op: "dial", Net: .network, Source: , Addr: , Err: &AddrError{Err: "unexpected address type", Addr: .address}}
}
if != nil {
return nil, &OpError{Op: "dial", Net: .network, Source: , Addr: , Err: } // c is non-nil interface containing nil pointer
}
return , nil
}
// ListenConfig contains options for listening to an address.
type ListenConfig struct {
// If Control is not nil, it is called after creating the network
// connection but before binding it to the operating system.
//
// Network and address parameters passed to Control function are not
// necessarily the ones passed to Listen. Calling Listen with TCP networks
// will cause the Control function to be called with "tcp4" or "tcp6",
// UDP networks become "udp4" or "udp6", IP networks become "ip4" or "ip6",
// and other known networks are passed as-is.
Control func(network, address string, c syscall.RawConn) error
// KeepAlive specifies the keep-alive period for network
// connections accepted by this listener.
//
// KeepAlive is ignored if KeepAliveConfig.Enable is true.
//
// If zero, keep-alive are enabled if supported by the protocol
// and operating system. Network protocols or operating systems
// that do not support keep-alive ignore this field.
// If negative, keep-alive are disabled.
KeepAlive time.Duration
// KeepAliveConfig specifies the keep-alive probe configuration
// for an active network connection, when supported by the
// protocol and operating system.
//
// If KeepAliveConfig.Enable is true, keep-alive probes are enabled.
// If KeepAliveConfig.Enable is false and KeepAlive is negative,
// keep-alive probes are disabled.
KeepAliveConfig KeepAliveConfig
// If mptcpStatus is set to a value allowing Multipath TCP (MPTCP) to be
// used, any call to Listen with "tcp(4|6)" as network will use MPTCP if
// supported by the operating system.
mptcpStatus mptcpStatusListen
}
// MultipathTCP reports whether MPTCP will be used.
//
// This method doesn't check if MPTCP is supported by the operating
// system or not.
func ( *ListenConfig) () bool {
return .mptcpStatus.get()
}
// SetMultipathTCP directs the [Listen] method to use, or not use, MPTCP,
// if supported by the operating system. This method overrides the
// system default and the GODEBUG=multipathtcp=... setting if any.
//
// If MPTCP is not available on the host or not supported by the client,
// the Listen method will fall back to TCP.
func ( *ListenConfig) ( bool) {
.mptcpStatus.set()
}
// Listen announces on the local network address.
//
// See func Listen for a description of the network and address
// parameters.
//
// The ctx argument is used while resolving the address on which to listen;
// it does not affect the returned Listener.
func ( *ListenConfig) ( context.Context, , string) (Listener, error) {
, := DefaultResolver.resolveAddrList(, "listen", , , nil)
if != nil {
return nil, &OpError{Op: "listen", Net: , Source: nil, Addr: nil, Err: }
}
:= &sysListener{
ListenConfig: *,
network: ,
address: ,
}
var Listener
:= .first(isIPv4)
switch la := .(type) {
case *TCPAddr:
if .MultipathTCP() {
, = .listenMPTCP(, )
} else {
, = .listenTCP(, )
}
case *UnixAddr:
, = .listenUnix(, )
default:
return nil, &OpError{Op: "listen", Net: .network, Source: nil, Addr: , Err: &AddrError{Err: "unexpected address type", Addr: }}
}
if != nil {
return nil, &OpError{Op: "listen", Net: .network, Source: nil, Addr: , Err: } // l is non-nil interface containing nil pointer
}
return , nil
}
// ListenPacket announces on the local network address.
//
// See func ListenPacket for a description of the network and address
// parameters.
//
// The ctx argument is used while resolving the address on which to listen;
// it does not affect the returned Listener.
func ( *ListenConfig) ( context.Context, , string) (PacketConn, error) {
, := DefaultResolver.resolveAddrList(, "listen", , , nil)
if != nil {
return nil, &OpError{Op: "listen", Net: , Source: nil, Addr: nil, Err: }
}
:= &sysListener{
ListenConfig: *,
network: ,
address: ,
}
var PacketConn
:= .first(isIPv4)
switch la := .(type) {
case *UDPAddr:
, = .listenUDP(, )
case *IPAddr:
, = .listenIP(, )
case *UnixAddr:
, = .listenUnixgram(, )
default:
return nil, &OpError{Op: "listen", Net: .network, Source: nil, Addr: , Err: &AddrError{Err: "unexpected address type", Addr: }}
}
if != nil {
return nil, &OpError{Op: "listen", Net: .network, Source: nil, Addr: , Err: } // c is non-nil interface containing nil pointer
}
return , nil
}
// sysListener contains a Listen's parameters and configuration.
type sysListener struct {
ListenConfig
network, address string
}
// Listen announces on the local network address.
//
// The network must be "tcp", "tcp4", "tcp6", "unix" or "unixpacket".
//
// For TCP networks, if the host in the address parameter is empty or
// a literal unspecified IP address, Listen listens on all available
// unicast and anycast IP addresses of the local system.
// To only use IPv4, use network "tcp4".
// The address can use a host name, but this is not recommended,
// because it will create a listener for at most one of the host's IP
// addresses.
// If the port in the address parameter is empty or "0", as in
// "127.0.0.1:" or "[::1]:0", a port number is automatically chosen.
// The [Addr] method of [Listener] can be used to discover the chosen
// port.
//
// See func [Dial] for a description of the network and address
// parameters.
//
// Listen uses context.Background internally; to specify the context, use
// [ListenConfig.Listen].
func (, string) (Listener, error) {
var ListenConfig
return .Listen(context.Background(), , )
}
// ListenPacket announces on the local network address.
//
// The network must be "udp", "udp4", "udp6", "unixgram", or an IP
// transport. The IP transports are "ip", "ip4", or "ip6" followed by
// a colon and a literal protocol number or a protocol name, as in
// "ip:1" or "ip:icmp".
//
// For UDP and IP networks, if the host in the address parameter is
// empty or a literal unspecified IP address, ListenPacket listens on
// all available IP addresses of the local system except multicast IP
// addresses.
// To only use IPv4, use network "udp4" or "ip4:proto".
// The address can use a host name, but this is not recommended,
// because it will create a listener for at most one of the host's IP
// addresses.
// If the port in the address parameter is empty or "0", as in
// "127.0.0.1:" or "[::1]:0", a port number is automatically chosen.
// The LocalAddr method of [PacketConn] can be used to discover the
// chosen port.
//
// See func [Dial] for a description of the network and address
// parameters.
//
// ListenPacket uses context.Background internally; to specify the context, use
// [ListenConfig.ListenPacket].
func (, string) (PacketConn, error) {
var ListenConfig
return .ListenPacket(context.Background(), , )
}
The pages are generated with Golds v0.7.3. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |