搜索
首页后端开发Golang多播在 golang 中的 Linux 上不起作用

多播在 golang 中的 Linux 上不起作用

php小编新一,今天要和大家讨论的是在golang中多播在Linux上不起作用的问题。多播是一种网络通信方式,可以在一个发送者和多个接收者之间传输数据。然而,在golang中,我们可能会遇到在Linux操作系统上多播不起作用的情况。本文将解释为什么会出现这个问题,并提供可能的解决方案。让我们开始吧!

问题内容

此代码发送和接收多播包。

此代码适用于 windows 10,但不适用于 linux:为什么?

已发送打包内容(ip 230.0.0.1,目标端口 9001),但应用程序未接收多播

数据包(ip 230.0.0.2,目标端口 9002)。

问题是什么?

为了测试我的应用程序,我使用了 linux vm:也许,这就是原因?

package main

import (
    "net"
    "os"
    "strconv"
    "time"

    "github.com/rs/zerolog"
    "golang.org/x/net/ipv4"
)

const device1_tx_multicastAddr = "230.0.0.1"
const device1_tx_udp_port = 9001
const device2_tx_multicastAddr = "230.0.0.2"
const device2_tx_udp_port = 9002
const packetTxDelayMs = 1000

// const ethName = "Ethernet" // Windows
const ethName = "eth0" // Linux

const modeDevice2 = false // Device 1
//const modeDevice2 = true // Device 2

var logConsole zerolog.Logger

func main() {
    logConsole = zerolog.New(os.Stderr).With().Timestamp().
        Str("module", "main").
        Logger().Output(zerolog.ConsoleWriter{Out: os.Stderr}).
        Level(zerolog.InfoLevel)

    // **********************************
    // Initialize Tx
    localInterface := getInterfaceByName(ethName)
    logConsole.Info().Str("func", "main").Msg("localInterface: " + ethName)

    tx_multicastAddr := device1_tx_multicastAddr
    rx_multicastAddr := device2_tx_multicastAddr
    tx_udp_port := device1_tx_udp_port
    rx_udp_port := device2_tx_udp_port

    if modeDevice2 {
        tx_multicastAddr = device2_tx_multicastAddr
        rx_multicastAddr = device1_tx_multicastAddr
        tx_udp_port = device2_tx_udp_port
        rx_udp_port = device1_tx_udp_port
    }

    logConsole.Info().Str("func", "main").Msg("Open Tx UDP port " + tx_multicastAddr + ":" + strconv.Itoa(tx_udp_port) + "...")
    remoteDeviceUdpAddr, err := net.ResolveUDPAddr("udp4", tx_multicastAddr+":"+strconv.Itoa(tx_udp_port))
    if err != nil {
        panic(err)
    }

    localDeviceUdpAddr, err2 := net.ResolveUDPAddr("udp4", localInterface.String()+":"+strconv.Itoa(rx_udp_port))
    if err2 != nil {
        panic(err2)
    }

    logConsole.Info().Str("func", "main").Msg("Listen UDP: " + localDeviceUdpAddr.String() + "...")
    localDevice, err2 := net.ListenUDP("udp4", localDeviceUdpAddr)
    if err2 != nil {
        panic(err2)
    }

    // **********************************
    // Initialize Rx
    udpReceiver := ipv4.NewPacketConn(localDevice)
    ief, errInterface := net.InterfaceByName(ethName)
    if errInterface != nil {
        localDevice.Close()
        panic(errInterface)
    }
    logConsole.Info().Str("func", "main").Msg("Join Multicast: " + rx_multicastAddr + "...")
    err = udpReceiver.JoinGroup(ief, &net.UDPAddr{IP: net.ParseIP(rx_multicastAddr)})

    if err != nil {
        localDevice.Close()
        panic(err)
    }

    // **********************************
    // Run Rx/Tx tasks
    go sendData(localDevice, remoteDeviceUdpAddr, packetTxDelayMs)
    receivedData(udpReceiver)
}

// *************************************************
func sendData(localDevice *net.UDPConn, remoteDeviceUdpAddr *net.UDPAddr, packetDelay uint) {
    data := []byte("1234567890")

    for {
        //logConsole.Info().Str("func", "sendData").Msg("Send...")
        _, err := localDevice.WriteTo(data, remoteDeviceUdpAddr)
        if err != nil {
            panic(err)
        }
        time.Sleep(time.Duration(packetDelay) * time.Millisecond)
    }
}
func receivedData(receiver *ipv4.PacketConn) {
    buf := make([]byte, 1500)
    for {
        n, _, _, err := receiver.ReadFrom(buf)
        if err == nil {
            logConsole.Info().Str("func", "receivedData").Msg("Receive Data: " + string(buf[0:n]))
        }
    }
}

// *************************************************
func getInterfaceByName(name string) net.IP {
    ief, err := net.InterfaceByName(name)
    if err != nil {
        panic(err)
    }
    addrs, err := ief.Addrs()
    if err != nil {
        panic(err)
    }

    var ipAddr net.IP
    for _, addr := range addrs {
        ipAddr = addr.(*net.IPNet).IP.To4()
        if ipAddr != nil {
            break
        }
    }
    if ipAddr == nil {
        panic("ipAddr is nil")
    }
    return ipAddr
}

解决方法

修改应用程序以侦听以下 ip 地址之一将使其在 linux 和 macos 上运行:

  • 多播组的ip地址(问题中的rx_multicastaddr
  • 通配符地址 (0.0.0.0)。

但尚不清楚当它侦听 nic 的 ip 地址(例如 192.168.0.5)时是否可以工作。根据我的测试和问题中的描述,它可以在 windows 上运行,但不能在 linux 或 macos 上运行。我还找不到描述这种行为的权威来源。

下面是一个接受标志的简化演示。

在设备 1 上,使用以下命令运行它(将接口名称替换为您的设备的名称):

go run . -listen 230.0.0.1:9001 -join 230.0.0.1:9001 -send 230.0.0.2:9002 -ifname eth0

在设备 2 上,使用以下命令运行它(将接口名称替换为您设备的接口名称):

go run . -listen 0.0.0.0:9002 -join 230.0.0.2:9002 -send 230.0.0.1:9001 -ifname ethernet
package main

import (
    "flag"
    "log"
    "net"
    "time"

    "golang.org/x/net/ipv4"
)

var (
    listen string
    join   string
    send   string
    ifname string
)

func main() {
    flag.StringVar(&listen, "listen", "230.0.0.1:9001", "")
    flag.StringVar(&join, "join", "230.0.0.1:9001", "the multicast group address to receive data from")
    flag.StringVar(&send, "send", "230.0.0.2:9002", "the multicast group address to send data to")
    flag.StringVar(&ifname, "ifname", "eth0", "the name of the interface")
    flag.Parse()

    itf, err := net.InterfaceByName(ifname)
    if err != nil {
        panic(err)
    }

    groupAddr, err := net.ResolveUDPAddr("udp4", join)
    if err != nil {
        panic(err)
    }

    c, err := net.ListenPacket("udp4", listen)
    if err != nil {
        panic(err)
    }
    defer c.Close()

    p := ipv4.NewPacketConn(c)
    if err := p.JoinGroup(itf, &net.UDPAddr{IP: groupAddr.IP}); err != nil {
        panic(err)
    }
    log.Printf("join multicast group %s, waiting...", join)

    go sendData(c, send)
    receivedData(p)
}

func sendData(c net.PacketConn, target string) {
    data := []byte(ifname)

    addr, err := net.ResolveUDPAddr("udp4", target)
    if err != nil {
        panic(err)
    }

    for {
        _, err := c.WriteTo(data, addr)
        if err != nil {
            panic(err)
        }
        time.Sleep(time.Second)
    }
}

func receivedData(receiver *ipv4.PacketConn) {
    buf := make([]byte, 1500)
    for {
        n, _, _, err := receiver.ReadFrom(buf)
        if err == nil {
            log.Printf("Receive Data from: %s\n", buf[0:n])
        }
    }
}

以上是多播在 golang 中的 Linux 上不起作用的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:stackoverflow。如有侵权,请联系admin@php.cn删除
7款颜值当道的 Linux 操作系统 !7款颜值当道的 Linux 操作系统 !Feb 09, 2024 pm 01:30 PM

Linux的发行版有很多,这里罗列7个漂亮的Linux发行版,可以说是Linux操作系统界的颜值担当了。elementaryOS网站:https://elementaryos.cnelementaryOS操作系统是最漂亮的Linux发行版之一。它基于macOS外观,同时为Linux用户提供了出色的用户体验。如果用户已经习惯使用macOS,则使用elementaryOS不会有任何问题。另外,elementaryOS操作系统基于Ubuntu,因此用户也可以轻松找到大量应用程序来完成任务。elemen

什么是Linux内核空间与用户空间?什么是Linux内核空间与用户空间?Feb 05, 2024 pm 12:57 PM

内核空间和用户空间对于32位操作系统而言,它的寻址空间(也称为虚拟地址空间或线性地址空间)大小为4G(即2的32次方)。这意味着一个进程可以拥有最大4G的地址空间。操作系统的核心是内核(kernel),它是与普通应用程序分离的,有权限访问受保护的内存空间和底层硬件设备。为了保证内核的安全,现代操作系统通常限制用户进程直接操作内核。通常,这通过将虚拟地址空间划分为两个部分来实现,即内核空间和用户空间。就Linux操作系统而言,最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF)被

7 款颜值 yyds 的 Linux 操作系统 !7 款颜值 yyds 的 Linux 操作系统 !Aug 01, 2023 pm 04:19 PM

Linux 的发行版有很多,这里罗列7个漂亮的 Linux 发行版。

linux系统下svn安装有几种方式linux系统下svn安装有几种方式Jun 14, 2023 am 10:50 AM

linux系统下svn安装方式常见有3种:1、使用操作系统预编译的软件包工具,如在“Ubuntu/Debian”上使用“sudo apt-get update”“sudo apt-get install subversion”进行安装;2、从源代码编译安装,官网下载源代码然后在Linux终端执行命令进行编译和安装;3、使用第三方包管理器如“Yum”进行安装,注意依赖项问题即可。

统信uos安装的配置要求统信uos安装的配置要求Feb 09, 2024 pm 07:03 PM

在这里为大家介绍一下统信uos安装的配置要求,统信uos是一款基于Linux内核的国产操作系统,具有稳定、安全、易用等特点,因此在国内得到了广泛的应用,为了确保统信uos的顺利安装和运行,我们需要了解它的配置要求。硬件配置统信uos的安装对硬件有一定的要求,具体如下:处理器:x86或x86_64架构的处理器,建议使用主频在1GHz以上的处理器。内存:至少2GB内存,建议使用4GB或以上内存。硬盘:至少20GB可用空间的硬盘,建议使用SSD固态硬盘以提高系统运行速度。显卡:支持DirectX9.0

Linux怎么识别到我插入的设备USB设备是什么设备的呢?Linux怎么识别到我插入的设备USB设备是什么设备的呢?Feb 09, 2024 pm 02:15 PM

一、前言在学习Linux操作系统时,你是否曾经有过这样的疑问:为什么我们的电脑能够识别并使用不同的USB设备呢?为什么Linux系统不会把鼠标当成键盘来使用呢?让我们一起来探讨一下USB设备在Linux系统中的识别和加载过程。二、USB设备的识别和加载当我们将一个USB设备插入电脑时,Linux内核会自动检测并加载相应的驱动程序,使设备能够正常工作。接下来,我们将深入探讨USB设备在Linux系统中的识别和加载过程。2.1USB控制器检测设备插入USB控制器是一个硬件设备,用于控制USB总线上的

linux操作系统包有哪些linux操作系统包有哪些Jun 14, 2023 am 10:41 AM

linux常用操作系统包有:1、Debian,稳定、通用、开放源代码的操作系统,全球使用最广泛的 Linux 发行版之一;2、Ubuntu,基于Debian的开放源代码操作系统,在桌面和笔记本电脑领域得到了广泛的应用;3、CentOS,基于Red Hat Enterprise Linux源码重新编译而来的社区发布版本,在企业服务器主机环境中非常流行等等。

CentOS安装指南:jemalloc与telnet一步到位CentOS安装指南:jemalloc与telnet一步到位Feb 09, 2024 pm 04:57 PM

在CentOS系统中,jemalloc和telnet都是非常实用的工具,jemalloc是一个通用的内存分配器,优化了多线程应用的性能,而telnet则是一个常用的远程登录工具,我们就来看看如何在CentOS系统中安装它们。安装jemalloc1.我们需要更新系统的软件包列表,打开终端,输入以下命令:```sqlsudoyumupdate```2.接下来,使用yum命令安装jemalloc:sudoyuminstalljemalloc3.安装完成后,可以使用以下命令验证jemalloc是否已成功

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
1 个月前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
4 周前By尊渡假赌尊渡假赌尊渡假赌

热工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用