系统编程-UDP

2024-09-04 03:28
文章标签 系统 编程 udp

本文主要是介绍系统编程-UDP,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

UDP

目录

UDP

引入

使用 UDP 的注意事项

一、单播的流程 -- 一对一

如何实现端口和地址重复绑定

二、广播的流程 -- 一对多

三、组播的流程 -- 多对多

加入组播,需要使用 setsockopt 函数

主要代码 -- 主要是发送方


引入

-- UDP协议的特点

  • 无连接性: UDP是无连接的协议,这意味着通信的双方不需要在通信之前建立连接。每个UDP数据报都是独立的,它们可以单独发送,没有依赖关系。

  • 不可靠性: UDP不提供数据传输的可靠性保证。它不会像TCP那样提供重传、确认和流量控制等机制。这意味着如果发送的数据丢失或者损坏,UDP不会自动重新发送,需要应用层自行处理。

  • 速度和低延迟: 由于没有连接状态维护和复杂的确认机制,UDP的开销比TCP小,因此在速度和延迟方面表现更好。这使得它适用于实时应用,如语音通话和在线游戏。

  • 数据报格式: UDP数据报包含了目标端口号和源端口号,这些信息用于将数据传递给正确的应用程序。但是,数据报本身没有保证按顺序到达或完整到达。

  • 无拥塞控制: UDP不具备TCP的拥塞控制机制,因此在网络拥塞的情况下,UDP数据报可能会丢失或延迟增加。

  • 广播和多播支持: UDP支持向特定组中的多个主机发送数据,这称为多播(Multicast)。也可以将数据报广播到网络中的所有主机,这称为广播(Broadcast)。

  • 适用场景: UDP适用于需要快速传输和实时性要求较高的应用,如语音和视频流、在线游戏、实时传感数据等。它不适用于需要可靠传输和数据完整性的场景,因为这些方面没有被UDP提供。

一对一 单播
一对多 广播
多对多 组播
在 UDP 中没有客户端和服务器之分
只有发送方和接收方

使用 UDP 的注意事项

-- 1 使用 udp 通信时 创建的套接字时用的参数与 tcp 不同

int socket(int domain, int type, int protocol) domain:AF_INET
type:SOCK_DGRAM -- 表示使用UDP
protocol:0
成功返回 udp 通信套节字
失败返回 -1

-- 2 udp 没有连接过程 所以没有服务器端和客户端

只有发送方和接收方
发送方需要不需要接收方的 ip 和 port?
100%要知道
所以接收方需要进行绑定操作将 ip 和 port 绑定到套接字上

-- 3 数据的发送和接收函数变了

#include <sys/types.h>
#include <sys/socket.h>
-- 发送函数
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen) 函数前四个参数跟 send 函数一模一样
后面两个参数需要填写接收方的 ip 和 port
dest_addr:填写接收方的 ip 和 port

-- 接收函数
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen)

-- 函数的参数:

  • src_addr:用来保存发送方的 ip 和 port
  • addrlen:填写一个保存了第二个参数结构体大小的变量的地址

一、单播的流程         -- 一对一

alt text

-- 接收方:

  • 1、创建通信套接字
    socket(AF_INET,SOCK_DGRAM,0)
  • 2、 bind 自己的 ip 和 port
    方便发送方 发送数据

-- 注:不进行bind操纵,套接字也会有ip和端口,但是是随机分配的,所以发送方无法发送数据,所以bind的主要作用是分配一个指定的ip和端口。

  • 3、 接收方 recvfrom 就可以了
    (1) char *inet_ntoa(struct in_addr in)
    接收方保存了发送的 ip 可以通过这个函数转化成点分十进制
    (2) uint16_t ntohs(uint16_t netshort)
    将大端的端口转化为小端

-- 发送方

  • 1、创建套节字
  • 2、直接发送至指定的 ip 和 port

-- 注:udp只管发送,那么他怎么知道发送给谁呢?
send_to函数有接受方的ip和port,接收方bind了ip和port,所以发送方和接收方就建立了联系。

如何实现端口和地址重复绑定

-- 在程序中写下如下代码即可

int opt = 1;
// sockfd 为需要端口复用的套接字
setsockopt(要复用的套接字, SOL_SOCKET, SO_REUSEADDR|SO_REUSEPORT, (const void *)&opt, sizeof(opt));

二、广播的流程 -- 一对多

alt text

-- 广播:特殊的地址:网络号.255

  • 例如:广播地址是192.168.110.255,其中主机号部分(最后一个八位字节)全部为255,表示网络中的所有主机。

-- 广播的地址是特定的

  • 在终端输入ifconfig,broadcast 后面就是广播地址

alt text

你向这个广播地址发送的消息会被转发到当前局域网的所有主机下
如向192.168.110.255 这个 IP 发送消息
192.168.110.0~192.168.110.254 这些 IP 都会收到消息
所有的 192.168.110.xxx 的地址都会收到消息

  • sento 中发送的端口 和 自身接受的端口 必须一样
    前提必须是同一个端口 port
    接收广播的套节字的端口必须跟发送至广播的端口一致

-- 要想使用广播必须要先激活广播

  • 使用 setsockopt 函数进行激活广播权限

  • int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen)

这个函数较为复杂
根据 level 的不同选项 optname 也会有不同的选项
level:选择 SOL_SOCKET
那么optname就选择SO_BROADCAST
optval:int 类型
optlen:sizeof(int)

-- 下面是激活广播的代码 直接粘贴复制使用即可

1、在广播的发送方添加以下代码,表示端口可以复用,激活广播权限

int opt = 1;
// sockfd 为需要端口复用的套接字
setsockopt(socket, SO_BROADCAST,&opt,sizeof(opt));

2、广播的接收方绑定的地址必须为 INADDR_ANY

struct sockaddr_in addr = {0};
addr.sin_family = AF_INET;  //表示用的是IPV4的地址
addr.sin_port = htons(PORT);//这里的PORT是共定义
addr.sin_addr.s_addr = INADDR_ANY; // 绑定地址必须为 INADDR_ANY

三、组播的流程 -- 多对多

alt text

-- 只有加入组播的套节字才可以进行接收
多播(组播)

  • 发送方需要加入一个特定的 ip 地址来实现组播,给这个组的IP和端口发送信息,会转发给所有在这个组播中的套接字

  • 接受方需要加入组播的组ip才能接收到信息

  • !!!这里发送方要发送ip和接收方要加入的组ip是一致的

  • 组播地址:D类地址

组播的 IP 地址:
224.0.0.0~224.0.0.255 为预留的组播地址(永久组地址),地址 224.0.0.0 保留不做分配,其它地址供路由
-- 协议使用 224.0.1.0~224.0.1.255 是公用组播地址,可以用于 Internet
224.0.2.0~238.255.255.255 为用户可用的组播地址(临时组地址),全网范围内有效 -- 我们可以用的地址
239.0.0.0~239.255.255.255 为本地管理组播地址,仅在特定的本地范围内有效

加入组播,需要使用 setsockopt 函数

-- 函数头文件

  • #include <sys/types.h>
  • #include <sys/socket.h>

-- 函数原型

  • int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);

-- 函数的参数

  • sockfd:套接字
  • level:选项的级别

IPPROTO_IP         -- IP 级别         -- 组播使用

  • optname:选项的名称

level 为 IPPROTO_IP
optname选IP_ADD_MEMBERSHIP         在指定接口上加入组播组

  • optval:当 optname 为 IP_ADD_MEMBERSHIP

optval 为该结构体

-- 结构体

struct ip_mreqn {       
struct in_addr imr_multiaddr; /* 多播组的地址 */
struct in_addr imr_address;
/* 本地的 IP 地址 */
int
imr_ifindex;
/* 接口索引 0 表示任意接口 */
};
imr_ifindex= ifnametoindex(“ens33”);
  • optlen:optval 的大小

  • 多播流程:
    1 创建 udp 套接字
    2 如果要接受多播的消息 需要加多播组 ,以下结构体为加入组播的代码

struct ip_mreqn addr = {0};
addr.imr_address.s_addr = INADDR_ANY;
addr.imr_multiaddr.s_addr = inet_addr("224.224.224.224");
setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&addr,sizeof(addr));

3 绑定自身的 ip 和 port
        port 需要跟多播的端口一样
4 recvfrom
        如果要向多播组发送消息 直接 sendto 多播的 ip 和 port 就可以了

alt text

主要代码 -- 主要是发送方

  • 单播发送方
char buff[30]={0};int num = 0;struct sockaddr_in R_addr = {0};R_addr.sin_family = AF_INET;R_addr.sin_port = htons(PORT);//发送的端口R_addr.sin_addr.s_addr = inet_addr(IP);//发送的 IPwhile(1){sprintf(buff,"num:%d",num++);sendto(fd,buff,sizeof(buff),0,(struct sockaddr *)&R_addr,sizeof(R_addr));perror("sendto()");sleep(1);}
  • 单播接收方
struct sockaddr_in addr = {0};addr.sin_family = AF_INET;addr.sin_port = htons(PORT);addr.sin_addr.s_addr = inet_addr(IP);bind(fd, (struct sockaddr*)&addr,sizeof(addr));char buff[50]={0};struct sockaddr_in S_addr = {0};int len = sizeof(S_addr);while(1){recvfrom(fd,buff,sizeof(buff),0,(struct sockaddr*)&S_addr,&len);printf("IP:%s\n",inet_ntoa(S_addr.sin_addr));//将大端转化为小端printf("PORT:%d\n",ntohs(S_addr.sin_port));printf("接收到:%s\n",buff);}
  • 广播发送方
char buff[30]={0};int num = 0;int opt = 1;setsockopt(fd,SOL_SOCKET,SO_BROADCAST,&opt,sizeof(opt));struct sockaddr_in R_addr = {0};R_addr.sin_family = AF_INET;R_addr.sin_port = htons(PORT);//发送的端口R_addr.sin_addr.s_addr = inet_addr(IP);//发送的 IPwhile(1){sprintf(buff,"num:%d",num++);sendto(fd,buff,sizeof(buff),0,(struct sockaddr *)&R_addr,sizeof(R_addr));perror("sendto()");sleep(1);}
  • 广播接收方
struct sockaddr_in addr = {0};addr.sin_family = AF_INET;addr.sin_port = htons(PORT);addr.sin_addr.s_addr = INADDR_ANY;bind(fd, (struct sockaddr*)&addr,sizeof(addr));char buff[50]={0};struct sockaddr_in S_addr = {0};int len = sizeof(S_addr);while(1){recvfrom(fd,buff,sizeof(buff),0,(struct sockaddr*)&S_addr,&len);printf("IP:%s\n",inet_ntoa(S_addr.sin_addr));//将大端转化为小端printf("PORT:%d\n",ntohs(S_addr.sin_port));printf("接收到:%s\n",buff);}
  • 组播发送方
char buff[30]={0};int num = 0;struct sockaddr_in R_addr = {0};R_addr.sin_family = AF_INET;R_addr.sin_port = htons(PORT);//发送的端口R_addr.sin_addr.s_addr = inet_addr(IP);//发送的 IPwhile(1){sprintf(buff,"num:%d!!!",num++);sendto(fd,buff,sizeof(buff),0,(struct sockaddr *)&R_addr,sizeof(R_addr));perror("sendto()");sleep(1);}
  • 组播接收方
struct sockaddr_in addr = {0};addr.sin_family = AF_INET;addr.sin_port = htons(PORT);addr.sin_addr.s_addr = INADDR_ANY;bind(fd, (struct sockaddr*)&addr,sizeof(addr));struct ip_mreqn addr1 = {0};addr1.imr_address.s_addr = INADDR_ANY;addr1.imr_multiaddr.s_addr = inet_addr("224.2.2.2");setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&addr1,sizeof(addr1));char buff[50]={0};struct sockaddr_in S_addr = {0};int len = sizeof(S_addr);while(1){recvfrom(fd,buff,sizeof(buff),0,(struct sockaddr*)&S_addr,&len);printf("IP:%s\n",inet_ntoa(S_addr.sin_addr));//将大端转化为小端printf("PORT:%d\n",ntohs(S_addr.sin_port));printf("接收到:%s\n",buff);}

这篇关于系统编程-UDP的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1134868

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

水位雨量在线监测系统概述及应用介绍

在当今社会,随着科技的飞速发展,各种智能监测系统已成为保障公共安全、促进资源管理和环境保护的重要工具。其中,水位雨量在线监测系统作为自然灾害预警、水资源管理及水利工程运行的关键技术,其重要性不言而喻。 一、水位雨量在线监测系统的基本原理 水位雨量在线监测系统主要由数据采集单元、数据传输网络、数据处理中心及用户终端四大部分构成,形成了一个完整的闭环系统。 数据采集单元:这是系统的“眼睛”,

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

【区块链 + 人才服务】可信教育区块链治理系统 | FISCO BCOS应用案例

伴随着区块链技术的不断完善,其在教育信息化中的应用也在持续发展。利用区块链数据共识、不可篡改的特性, 将与教育相关的数据要素在区块链上进行存证确权,在确保数据可信的前提下,促进教育的公平、透明、开放,为教育教学质量提升赋能,实现教育数据的安全共享、高等教育体系的智慧治理。 可信教育区块链治理系统的顶层治理架构由教育部、高校、企业、学生等多方角色共同参与建设、维护,支撑教育资源共享、教学质量评估、

软考系统规划与管理师考试证书含金量高吗?

2024年软考系统规划与管理师考试报名时间节点: 报名时间:2024年上半年软考将于3月中旬陆续开始报名 考试时间:上半年5月25日到28日,下半年11月9日到12日 分数线:所有科目成绩均须达到45分以上(包括45分)方可通过考试 成绩查询:可在“中国计算机技术职业资格网”上查询软考成绩 出成绩时间:预计在11月左右 证书领取时间:一般在考试成绩公布后3~4个月,各地领取时间有所不同

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识