这里是net.ListenIP()的源码:
// ListenIP listens for incoming IP packets addressed to the local
// address laddr. The returned connection's ReadFrom and WriteTo
// methods can be used to receive and send IP packets with per-packet
// addressing.
func ListenIP(netProto string, laddr *IPAddr) (*IPConn, error) {
net, proto, err := parseNetwork(netProto)
if err != nil {
return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: err}
}
switch net {
case "ip", "ip4", "ip6":
default:
return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: UnknownNetworkError(netProto)}
}
fd, err := internetSocket(net, laddr, nil, noDeadline, syscall.SOCK_RAW, proto, "listen", noCancel)
if err != nil {
return nil, &OpError{Op: "listen", Net: netProto, Source: nil, Addr: laddr.opAddr(), Err: err}
}
return newIPConn(fd), nil
}
它创建一个原始套接字,在 linux 上,IPPROTO_RAW socket 仅用于发送。 TCP 和 UDP 数据包永远不会传递到原始套接字,它们总是由内核协议栈处理。 ICMP 数据包的副本被传递到匹配的原始套接字。所有其他发往未由内核子系统处理的协议的数据包都被传递到原始套接字。