添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
玩滑板的黄花菜  ·  python ...·  3 周前    · 
狂野的圣诞树  ·  Golang ...·  1 年前    · 
9976254  ·  【Golang ...·  2 年前    · 
9976254  ·  Ubuntu Golang项目编译报错 ...·  2 年前    · 
细心的佛珠  ·  通过 Nexus3 搭建 pypi ...·  1 月前    · 
爱喝酒的哑铃  ·  package.json与package-l ...·  1 年前    · 
Stack Overflow for Teams is a private, secure spot for you and your coworkers to find and share information. Learn more

Task at hand is to bind a socket specifically to address 1.0.0.2:520 (assigned to eth2), then read multicast UDP packets addressed to 224.0.0.9:520.

I am trying the code below, based on https://godoc.org/golang.org/x/net/ipv4

Unfortunately, result is this debbuging message is never reached: log.Printf("udpReader: recv %d bytes from %s to %s on %s", n, cm.Src, cm.Dst, ifname)

I know eth2 is receiving the desired packets because I have this packet sniffer running on it:

sudo tcpdump -n -i eth2
18:40:28.571456 IP 1.0.0.1.520 > 224.0.0.9.520: RIPv2, Request, length: 24
18:40:29.556503 IP 1.0.0.1.520 > 224.0.0.9.520: RIPv2, Response, length: 64

This is the sample code. Can you spot why doesn't it work?

package main
import (
    "fmt"
    "log"
    "net"
    "golang.org/x/net/ipv4"
func main() {
    if err := interfaceAdd("eth2"); err != nil {
        log.Printf("main: error: %v", err)
    log.Printf("main: waiting forever")
    <-make(chan int)
func interfaceAdd(s string) error {
    iface, err1 := net.InterfaceByName(s)
    if err1 != nil {
        return err1
    addrList, err2 := iface.Addrs()
    if err2 != nil {
        return err2
    for _, a := range addrList {
        addr, _, err3 := net.ParseCIDR(a.String())
        if err3 != nil {
            log.Printf("interfaceAdd: parse CIDR error for '%s' on '%s': %v", addr, s, err3)
            continue
        if err := join(iface, addr); err != nil {
            log.Printf("interfaceAdd: join error for '%s' on '%s': %v", addr, s, err)
    return nil
func join(iface *net.Interface, addr net.IP) error {
    proto := "udp"
    var a string
    if addr.To4() == nil {
        // IPv6
        a = fmt.Sprintf("[%s]", addr.String())
    } else {
        // IPv4
        a = addr.String()
    hostPort := fmt.Sprintf("%s:520", a) // rip multicast port
    // open socket (connection)
    conn, err2 := net.ListenPacket(proto, hostPort)
    if err2 != nil {
        return fmt.Errorf("join: %s/%s listen error: %v", proto, hostPort, err2)
    // join multicast address
    pc := ipv4.NewPacketConn(conn)
    if err := pc.JoinGroup(iface, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 9)}); err != nil {
        conn.Close()
        return fmt.Errorf("join: join error: %v", err)
    // request control messages
        if err := pc.SetControlMessage(ipv4.FlagTTL|ipv4.FlagSrc|ipv4.FlagDst|ipv4.FlagInterface, true); err != nil {
            // warning only
            log.Printf("join: control message flags error: %v", err)
    go udpReader(pc, iface.Name, addr.String())
    return nil
func udpReader(c *ipv4.PacketConn, ifname, ifaddr string) {
    log.Printf("udpReader: reading from '%s' on '%s'", ifaddr, ifname)
    defer c.Close()
    buf := make([]byte, 10000)
    for {
        n, cm, _, err := c.ReadFrom(buf)
        if err != nil {
            log.Printf("udpReader: ReadFrom: error %v", err)
            break
        // make a copy because we will overwrite buf
        b := make([]byte, n)
        copy(b, buf)
        log.Printf("udpReader: recv %d bytes from %s to %s on %s", n, cm.Src, cm.Dst, ifname)
    log.Printf("udpReader: exiting '%s'", ifname)

Output:

2016/02/09 18:44:20 interfaceAdd: join error for 'fe80::a00:27ff:fe52:9575' on 'eth2': join: udp/[fe80::a00:27ff:fe52:9575]:520 listen error: listen udp [fe80::a00:27ff:fe52:9575]:520: bind: invalid argument
2016/02/09 18:44:20 main: waiting forever
2016/02/09 18:44:20 udpReader: reading from '1.0.0.2' on 'eth2'
                Just to make it christal clear: The task is not to bind to the interface which listens on that IP, but specifically and positively to the IP itself?
– Markus W Mahlberg
                Feb 9 '16 at 20:28
                The task is to receive packets addressed to 224.0.0.9, but only on an specific interface. Binding to the IP address is the mechanism I suppose I should use to achieve that goal.
– Everton
                Feb 9 '16 at 20:33
                Nope. Identify the interface to bind to by its IP, then bind to it and join the multicast group.
– Markus W Mahlberg
                Feb 9 '16 at 20:56
                Well, I think that's what the code is doing: ListenPacket() binds to interface's IP address, then JoinGroup() joins the multicast group. However, it's not working. Can you tell where the error is?
– Everton
                Feb 9 '16 at 21:02

In order to create multiple interface-specific sockets to receive packets addressed to the same multicast address (224.0.0.9:520), my original Go code was missing three major issues:

  • In order to bind multiple sockets to same UDP port, set syscall.SO_REUSEADDR
  • In order to restrict socket to specific interface, set syscall.SO_BINDTODEVICE
  • Bind the UDP sockets to 0.0.0.0:520
  • Find full sample code here: http://play.golang.org/p/NprsZPHQmj

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.