Golang笔记:UDP基础使用与广播

2023-11-18

目的

UDP是比较基础常用的网络通讯方式,这篇文章将介绍Go语言中UDP基础使用的一些内容。

本文中使用 Packet Sender 工具进行测试,其官网地址如下:
https://packetsender.com/

基础说明

UDP是一种面向无连接的通讯,抛开业务逻辑来说UDP使用上不需要像TCP那样先建立连接才能使用,收就是收、发就是发,干净利落。

很多语言中UDP使用一般逻辑如下:

  1. 建立UDP类型Socket对象,用于数据收发;
  2. 发送时只需要指定 对方地址与端口号 就可以发送数据;
  3. 接收的话只需要监听 自身某个端口号
  4. 如果要实现双向通讯可以使用同一个Socket对象进行监听与发送;
  5. 很多时候都有一对一通讯的需求,所以标准库中都提供了一些面向连接的方法。但其实这只是在应用层面上的处理而已,实际上底层还是收就是收发就是发;

这里特别想要吐槽的一点是Go标准库使用UDP收发数据并不是给的Socket对象,而都是需要通过 UDPConn 这个对象,这个思路就是上面的第5条思路了。我个人使用UDP单发送时比较喜欢上面第2条的方式,就是单纯的发送。在Go中找了半天没有找到这种可以直接发送的方式,感觉挺变扭的。

本文中用到的一些函数与方法如下:

// 从字符串获得IP地址
func ResolveUDPAddr(network, address string) (*UDPAddr, error)

// 建立UDP(预)连接
func DialUDP(network string, laddr, raddr *UDPAddr) (*UDPConn, error)
// 启动UDP监听
func ListenUDP(network string, laddr *UDPAddr) (*UDPConn, error)

// 建立连接的情况下发送数据
func (c *UDPConn) Write(b []byte) (int, error)
// 建立连接的情况下读取数据
func (c *UDPConn) Read(b []byte) (int, error)

// 获取远程地址
func (c *UDPConn) RemoteAddr() Addr

// 接收数据并获得远程地址
func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error)
// 向指定地址发送数据
func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error)

作为服务器使用

下面是个作为服务器使用的简单例子,功能是监听指定端口号,收到数据时输出到控制台,然后向远程端应答消息:

package main

import (
	"fmt"
	"net"
	"os"
)

func main() {
	udpAddr, err := net.ResolveUDPAddr("udp4", ":22333") // 转换地址,作为服务器使用时需要监听本机的一个端口
	                                                     // 端口号写 0 可以由系统随机分配可用的端口号
	checkError(err)
	conn, err := net.ListenUDP("udp", udpAddr) // 启动UDP监听本机端口
	checkError(err)

	for {
		var buf [128]byte
		len, addr, err := conn.ReadFromUDP(buf[:]) // 读取数据,返回值依次为读取数据长度、远端地址、错误信息 // 读取操作会阻塞直至有数据可读取
		checkError(err)
		fmt.Println(string(buf[:len])) // 向终端打印收到的消息

		_, err = conn.WriteToUDP([]byte("233~~~"), addr) // 写数据,返回值依次为写入数据长度、错误信息 // WriteToUDP()并非只能用于应答的,只要有个远程地址可以随时发消息
		checkError(err)
	}
}

func checkError(err error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "Fatal error %s", err.Error())
		os.Exit(1)
	}
}

在这里插入图片描述

作为客户端使用

作为客户端使用也不复杂,下面是个简单的示例:

package main

import (
	"fmt"
	"net"
	"os"
	"time"
)

func main() {
	udpAddr, err := net.ResolveUDPAddr("udp4", "192.168.31.189:53771") // 转换地址,作为客户端使用要向远程发送消息,这里用远程地址与端口号
	checkError(err)
	conn, err := net.DialUDP("udp", nil, udpAddr) // 建立连接,第二个参数为nil时通过默认本地地址(猜测可能是第一个可用的地址,未进行测试)发送且端口号自动分配,第三个参数为远程端地址与端口号
	checkError(err)

	go receive(conn) // 使用DialUDP建立连接后也可以监听来自远程端的数据

	for {
		_, err = conn.Write([]byte("naisu233~~~")) // 向远程端发送消息
		checkError(err)
		time.Sleep(4 * time.Second) // 等待4s
	}
}

func receive(conn *net.UDPConn) {
	for {
		var buf [128]byte
		len, err := conn.Read(buf[0:]) // 读取数据 // 读取操作会阻塞直至有数据可读取
		checkError(err)
		fmt.Println(string(buf[0:len]))
	}
}

func checkError(err error) {
	if err != nil {
		fmt.Fprintf(os.Stderr, "Fatal error %s", err.Error())
		os.Exit(1)
	}
}

在这里插入图片描述

广播

广播主要就是指发送时向内网中所有设备发送消息了,操作上最主要就是发送消息时地址使用 广播地址 ,广播地址计算方式可以参考下面文章:

《UDP IPv4广播地址计算(附Node.js示例代码)》
https://blog.csdn.net/Naisu_kun/article/details/127221349

下面是Go中广播地址获取代码:

// 返回广播地址列表
func GetBroadcastAddress() ([]string, error) {
	broadcastAddress := []string{}

	interfaces, err := net.Interfaces() // 获取所有网络接口
	if err != nil {
		return broadcastAddress, err
	}

	for _, face := range interfaces {
		// 选择 已启用的、能广播的、非回环 的接口
		if (face.Flags & (net.FlagUp | net.FlagBroadcast | net.FlagLoopback)) == (net.FlagBroadcast | net.FlagUp) {
			addrs, err := face.Addrs() // 获取该接口下IP地址
			if err != nil {
				return broadcastAddress, err
			}
			for _, addr := range addrs {
				if ipnet, ok := addr.(*net.IPNet); ok { // 转换成 IPNet { IP Mask } 形式
					if ipnet.IP.To4() != nil { // 只取IPv4的
						var fields net.IP // 用于存放广播地址字段(共4个字段)
						for i := 0; i < 4; i++ {
							fields = append(fields, (ipnet.IP.To4())[i]|(^ipnet.Mask[i])) // 计算广播地址各个字段
						}
						broadcastAddress = append(broadcastAddress, fields.String()) // 转换为字符串形式
					}
				}
			}
		}
	}

	return broadcastAddress, nil
}

因为工作原因我的电脑上有非常多的实体的或是虚拟的网卡,下面是我电脑上部分网络情况:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

下面是广播地址获取演示:
在这里插入图片描述

需要注意的是如果设备上有多个网卡的话就可能有多个广播地址,要全局广播的话就要向每个广播地址分别发送消息。操作上来说可以用服务器的方式,拿到 UDPConn 对象后使用 WriteToUDP 方法分别向各个广播地址发送消息。

总结

UDP的使用比较简单,这里没有提及的是组播和任意播功能,因为我不太用这两种所以这里也就不介绍了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Golang笔记:UDP基础使用与广播 的相关文章

  • 如何在 Docker 上发布 UDP 端口?

    如何将 UDP 端口从 Docker 容器转发到主机 使用 p 标志并添加 udp端口号的后缀 p 53160 53160 udp 完整命令 sudo docker run p 53160 53160 p 53160 53160 udp p
  • 我应该对 UDP 使用(非阻塞)NIO 吗?

    根据这个帖子 https stackoverflow com questions 569555 non blocking udp i o vs blocking udp i o in java UDP 只是不阻塞 使用 非阻塞 NIO AP
  • 在不使用环回网络的情况下将数据包转发到同一主机中的服务

    我有这个 libnetfilter queue 应用程序 它根据某些 iptables 规则从内核接收数据包 在直接讨论我的问题之前 我提供了一个示例可行代码和其他工具来设置测试环境 以便我们的问题定义和可能的解决方案可以更加准确和稳健 以
  • UDP 数据报中发送的消息未经过净化?

    我的代码如下 一切都按照我想要的方式进行 但是当我的消息收到时 它们的末尾有很多框 有点像这样 消息 你好 如何才能让接收和打印的内容仅为 Message hello 我非常感谢任何帮助 import java io import java
  • 丢包纠错码 (UDP)

    我不知道要寻找什么 因为我从 纠错代码 中得到的只是与您不知道错误位置的情况相关的内容 因此 这些代码比我需要的要复杂得多 而且效率低下 在下文中 请注意位等于数据包 因为只有整个数据包可能会丢失 因此位类比非常适合 是否有 ECC 考虑到
  • 如何设置Winsock UDP套接字?

    我想创建一个仅向客户端发送数据的 Winsock UDP 套接字 我希望内核为我选择一个可用的端口 另一方面 我想指出要使用哪个本地 IP 因为我正在运行一些网卡 我尝试过梳理迷宫般的套接字选项 以及将套接字地址中的端口绑定设置为 0 但均
  • Spark Scala UDP 在侦听端口上接收

    中提到的例子http spark apache org docs latest streaming programming guide html http spark apache org docs latest streaming pro
  • 具有多个接口的 Python UDP 套接字

    我正在 Windows XP 机器上用 python2 7 编写脚本 本机使用不同的网卡连接到多个网络 我遇到了一个问题 我已将 UDP 套接字绑定到特定接口 我知道您可以通过仅提供网卡现有的 IP 地址来在 Windows 中完成此操作
  • C++ 反序列化通过 UDP 从 C# 应用程序发送的对象

    我有一个申请c 它连接到另一个应用程序 编写为c 通过UDP 我更喜欢高性能的解决方案 因为我希望测量事件客户端 某些处理服务器端和客户端处理完成的响应之间的时间 本质上是 往返延迟 我有一个 C 对象 例如 public class Pa
  • UDP sendto 上的 ECONNREFUSED 错误

    我在使用正在写入的应用程序时遇到一些无法解释的行为 使用 sendto 向多个端口发送 UDP 数据 所有端口均使用套接字 PF INET SOCK DGRAM 0 为了一组客户端读取进程的利益 这些 sendto 偶尔会不可预测地触发经济
  • C#/Unity - 无法从异步方法调用 Unity 方法

    我正在使用Unity3D 这是我的异步方法 private void Receive IAsyncResult ar try IPEndPoint ipEndPoint null byte data udpClient EndReceive
  • iOS 14 在进行本地网络广播时给出“操作系统错误:错误的文件描述符,errno = 9”

    做一点Jeopardy 风格问答 https stackoverflow blog 2011 07 01 its ok to ask and answer your own questions here 我正在 Flutter 中开发一个应
  • 如何在QT中发送和接收UDP数据包

    我正在 QT 中编写一个小型应用程序 它通过本地网络发送广播 UDP 数据包 并等待来自网络上的一个或多个设备的 UDP 响应数据包 创建套接字并发送广播数据包 udpSocketSend new QUdpSocket this udpSo
  • netty 4.x.x 中的 UDP 广播

    我们需要使用 Netty 4 0 0 二进制文件通过 UDP 通道广播对象 Pojo 在 Netty 4 0 0 中 它允许我们仅使用 DatagramPacket 类来发送 UDP 数据包 此类仅接受 ByteBuf 作为参数 还有其他方
  • 我刚刚在哪个适配器上收到此 UDP 数据包?

    我正在尝试用 C 编写一个 BOOTP 服务器 我正在接收并解析来自客户端的 BOOTP 数据包 我需要回复我的服务器 IP 地址 问题是 计算机可以有多个网络适配器 客户端还没有 IP 地址 有什么方法可以查出 UDP 数据包是在哪个适配
  • Windows 操作系统中无法访问的 IP 套接字关闭时间

    这些代码通过用户数据报协议提供发送数据 下面有两个代码 当我使用第一个代码来处理无法访问的 IP 地址时 我得到了三秒的延迟 请查看新结果标题 只需打开新的 C 控制台应用程序并将这些代码粘贴到其中 第一个代码 using System u
  • 使用 STUN 打孔

    我目前正在尝试通过 Internet 发送 UDP 消息 并且必须为端点 A 和 B 都位于 NAT 后面 设置防火墙 为此 我想使用 STUN 服务器进行打孔 当 A 创建对 STUN 服务器的请求 例如 私有 85 1 1 12 600
  • Python UDP广播不发送

    我正在尝试从 Python 程序到两个 LabView 程序进行 UDP 广播 我似乎无法发送广播 我不确定我的套接字初始化错误在哪里 广播似乎足够简单 据我所知 其他电脑没有收到任何数据 另外 我将来还需要这个程序来接收来自其他电脑的数据
  • F1 2019 UDP解码

    我目前正在为 F1 方向盘开发自己的显示器 F1 2019 由codemasters提供 通过UDP发送数据 该数据存储在字节数组中 我在解码返回的数组时遇到一些问题 问题是我得到了很多信息 但我不知道如何处理它们 我将向您介绍我所尝试过的
  • 在 PowerShell 中通过 UDP 发送和接收数据

    我正在尝试编写一个脚本来使用 PowerShell 进行测试和应用 测试应包括通过 UDP 向远程服务器发送字符串 然后读取该服务器的响应并对结果执行某些操作 我需要的唯一帮助是脚本的中间两个步骤 发送字符串 然后 接收响应 在端口 UDP

随机推荐

  • HADOOP集群搭建

    安装步骤 机器mini yum mini2 mini3 mini4 注意 下面的步骤在4台机子上都要做的操作 1先将虚拟机的网络模式选为NAT 2修改主机名 vi etc sysconfig network NETWORKING yes H
  • git:kex_exchange_identification:Connection closed by 52.74.223.119 port 22

    使用Rider的git进行push操作时提示 kex exchange identification Connection closed by remote host Connection closed by 52 74 223 119 p
  • AJAX 缓存处理

    关于AJAX请求服务器后缓存数据 造成没有及时刷新的问题 最近在做项目的时候 使用了ajax去请求服务器的数据 刚开始还可以 我测试一切运行正常 我不是专业的测试人员哈 所以还是有些问题没有测出来哈 后来ajax请求的数据变化了 但是页面数
  • 设计模式之命令模式

    在日常生活中 我们常常会遇到这样一些问题 需要向某些对象发送请求 但是并不知道请求的接收者是谁 也不知道被请求的操作是哪个 我们只需在程序运行时指定具体的请求接收者即可 此时 可以使用命令模式来进行设计 使得请求发送者与请求接收者消除彼此之
  • react 显示当前时间_react中monent如何获取日期?

    方法 1 使用 npm install moment save 安装moment 2 在组件中使用import语句引入moment 3 使用monent提供的方法来获取日期 例 moment format 获取当前时间 本教程操作环境 wi
  • OneFlow 中的 Softmax

    Softmax 是深度学习模型中的常见算子 PyTorch 的 Softmax 算子直接调用 cuDNN 的接口 而 OneFlow 内部针对输入数据的类别数量 采用3个 kernel 来分别处理 在多数情况下都可以获得比 cuDNN 更优
  • 【Git】(三)回退版本

    1 git reset命令 1 1 回退至上一个版本 git reset hard HEAD 1 2 将本地的状态回退到和远程的一样 git reset hard origin master 注意 谨慎使用 hard 参数 它会删除回退点之
  • redis必杀高级:安全

    题记 我们可以通过 redis 的配置文件设置密码参数 这样客户端连接到 redis 服务就需要密码验证 这样可以让你的 redis 服务更安全 例如 设置密码 查看是否设置了密码验证 127 0 0 1 6379 gt CONFIG ge
  • 【Java日志】你真的知道怎么使用Java日志API吗?

    你真的知道怎么使用Java日志API吗 一 背景 二 Java日志API错误使用示例 1 占位符的错误使用示例 2 异常日志的错误使用示例 三 推荐一个学习Java日志的项目 一 背景 在平时的开发过程中 常常看到一些编码不规范的打印日志的
  • Flask读取RTSP视频流,及其简单的一个案例

    Flask读取RTSP视频流 及其简单的一个案例 此章节包括通过是使用Flask可以实时地显示RTSP视频流 代码确实非常简单 源于Github 主要为为Nvidia Deepstream极致细节 3 Deepstream Python R
  • 华为怎么显示返回按键_华为怎么把返回那三个键调出来

    华为怎么把返回那三个键调出来 其实这个方法一点都不难 1 首先在华为nova3的桌面找到 设置 并点击进入 2 点击打开 系统 3 在系统菜单下 点击进入 系统导航 4 点击勾选 屏幕内虚拟导航栏 即可打开虚拟导航 不勾选即可直接关闭虚拟导
  • vscode配置快捷键注释模板

    文章目录 前言 一 打开配置项 1 首选项编辑配置 2 新建代码片段 3 配置注释文件名 二 新建代码注释模板 三 注释使用 前言 本篇文章可以在vscode中配置快捷键显示代码的信息注释 如作者 描述 创建时间等 一 打开配置项 1 首选
  • SD卡中FAT32文件格式快速入门(图文详细介绍)

    说明 MBR Master Boot Record 主引导记录 DBR DOS Boot Record 引导扇区 FAT File Allocation Table 文件分配表 硬件 本文SD卡为Kingston 4GB FAT32格式 簇
  • 【Python】 Pandas数据导入与导出

    数据读取 import pandas as pd data pd read csv data csv 读取数据文件 print data 数据索引与查看 x data loc x 读取表头为 x 的那一列的数据 print x y data
  • 如何自学现代计算机科学(转)

    简介 这里收集了很多学习资源 都是关于一些适合本科生学习的计算机科学 话题 Topics 这里仅仅只提供 话题 列表 而不会提供诸如知识点剖析 练习题等内容 如果你对某一个话题特别感兴趣 想深入研究一下 但又买不起文中提到的书籍 实体书 那
  • 使用docker搭建FastDFS文件系统

    使用docker搭建FastDFS文件系统 1 拉取fastdfs镜像 docker search fastdfs 这里要选择 delron fastdfs 镜像 docker pull delron fastdfs 2 启动容器 2 1
  • 车祸相关公开数据集(免费下载)

    Vehicle Collisions 纽约市机动车与人相撞 背景描述 这是 2021 年在纽约发生的人与机动车碰撞事故的数据 仅过滤掉超过 1 000 美元的受伤或死亡案件 总结了事件的日期和时间 受伤的位置以及警方对事件的描述 数据说明
  • Dubbo源码分析-Spring与Dubbo整合原理与源码分析(二)

    Spring与Dubbo整合的整体流程 基于apache dubbo 2 7 15 因为dubbo有较多的兼容以前的代码比如 DubboReference 以前就有两个版本 Reference 和 com alibaba dubbo con
  • list 分组_学习笔记系列_10_数据聚合与分组操作

    开篇导包 一 数据聚合 df groupby 详解 DataFrame 参数 by 用作分组的条件对象 mapping function label or list of labels axis 轴方向 0 or index 1 or co
  • Golang笔记:UDP基础使用与广播

    文章目录 目的 基础说明 作为服务器使用 作为客户端使用 广播 总结 目的 UDP是比较基础常用的网络通讯方式 这篇文章将介绍Go语言中UDP基础使用的一些内容 本文中使用 Packet Sender 工具进行测试 其官网地址如下 http