UDP传输协议Linux C语言实战

文章目录

  • 1.UDP简介
    • 1.1特点
    • 1.2 UDP协议头部格式
      • 1.2.1 **UDP头部**:
      • 1.2.2 **头部意义**:
      • 1.2.3 **头部参数**:
    • 1.3 UDP数据长度控制
    • 1.4 UDP协议建立框架
  • 2. 函数介绍
    • 2.1 sendto函数
    • 2.2 recvform函数
    • 2.3 其他函数
  • 3.实例
    • 3.1 通用结构体、IPV4结构体、IPV6结构体
    • 3.2 框架搭建
      • 3.2.1 client
      • 3.2.2 server
    • 3.3 服务端和客户端编写
      • 3.3.1 client_udp.c
      • 3.3.2 sever_udp.c
      • 3.3.3 终端结果
  • 4.总结

摘要:这篇文章是对UDP传输协议的讲解,包括基础知识、主要函数,最后通过在linux上用C语言建立客户端和服务端实例对UDP的认识更加深刻。
关键词:UDP、sendto、recvfrom。

1.UDP简介

1.UDP(User Datagram protocol)传输协议是TCP/IP网络协议下,传输层的一中面向报文传输方式。

1.1特点

1.无连接特性:传输时不用建立连接,服务端也不用做出响应。
2. 不可靠传输:没有TCP那样复杂,发送端只管发送数据,不会管接收端的感受,真是个无情的man。
3. 快速传输:由于 UDP 没有连接建立和可靠传输机制带来的开销,它可以非常快速地发送数据。
4.面向数据报:应用层发送多少,UDP传输层就给网络层发送多少数据。

1.2 UDP协议头部格式

在这里插入图片描述

1.2.1 UDP头部

UDP头部没有TCP头部那么复杂,只占了8个字节,而TCP头部最小20各字节,根据可选项参数还能扩展到60个字节,TCP头部长度标识只占4位,但是TCP头部的每一个值表示4字节数目,所以最大长度2^4*4=60。

1.2.2 头部意义

UDP头部和TCP头部表示的意思不同,UDP头部是整个数据报的长度,因为UDP头部固定8个字节,所以不用标识多长。
更多TCP信息请查看
TCP三次握手,四次挥手,通俗易懂!!!
Linux C语言TCP协议实战

1.2.3 头部参数

源端口号:这个可有可无,数据报是无连接的,只需给数据报指定发送方就行了(sendto函数后面会介绍)。由于不需要消耗额外的资源消耗在连接、同步、拥塞控制、流量控制等等机制上,这也是UDP传输快速的原因。
目的端口号:数据报的的接收端必须指定,网络层和链路层通过路由、链路等方法,将数据迅速的发送到指定端口。
UDP长度:指定了数据报的长度,UDP头部固定长度无需指定。
校验和:确认数据是否错误。

1.3 UDP数据长度控制

下面这两张图的意思是设置了IP_MTU_DESCOVER套接字选项,发送数据端会追踪目标IP的最大传输单元(MTU)的大小,而不是SOCK_STREAM数据形式的(也就是不是TCP协议)传输协议会默认使用MTU追踪,默认选项可以在/proc/sys/net/ipv4/ip_no_pmtu_disc文件下设置,从最后一张图中默认为0,默认使用IP_PMTUDISC_WANT选项,这个选项会根据追踪到的目的端MTU的大小来控制数据报的尺寸,关闭这个选项数据超过MTU(加协议头部)UDP会进行数据分片,但是不建议关闭,这样会影响到UDP数据的发送速度,这些是IP层的知识,不多讲,我也懂的不多。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.4 UDP协议建立框架

UDP协议没有一对一建立连接,只需要确定服务器的IP和端口就可以了,所以不用多线程和和多进程进行处理。
在这里插入图片描述

2. 函数介绍

2.1 sendto函数

向指定端口发送数据,在函数中,出现sockaddr结构体,发送端可以不用绑定端口,直接发送数据。

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr*dest_addr, socklen_t addrlen);
/*
sockfd: socket函数返回的文件描述符
buf:  数据
len: 数据长度
flags: 可选参数一般填0,更多选项可在man sendto中查看
dest_addr:  网络通用结构体
addrlen:  结构体长度
*/

2.2 recvform函数

阻塞等待接收数据,接收端可以不用绑定端口直接接收数据。

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
sockfd: socket函数返回的文件描述符
buf:  数据
len: 数据长度
flags: 可选参数一般填0,更多选项可在man sendto中查看
src_addr:  网络通用结构体
addrlen:结构体长度

2.3 其他函数

关于端口和IP地址的主机字节序和网络字节序可以在这篇文章查找:TCP/IP传输协议,易懂!!!
实战代码中用到的其他网络相关函数可以在这篇文章中查找:Linux C语言TCP协议实战

3.实例

3.1 通用结构体、IPV4结构体、IPV6结构体

struct sockaddr {unsigned short sa_family;  // 地址族,用于指定地址类型,例如 AF_INET(IPv4)、AF_INET6(IPv6)等char sa_data[14];          // 地址数据,具体格式和长度取决于地址族的不同
};IPV6结构体
struct sockaddr_in6 {sa_family_t sin6_family;   /* 地址族,这里是 AF_INET6,表示 IPv6 地址 */in_port_t sin6_port;       /* 端口号,使用网络字节序 */uint32_t sin6_flowinfo;    /* IPv6 流信息 */struct in6_addr sin6_addr;  /* IPv6 地址 */uint32_t sin6_scope_id;    /* IPv6 范围 ID */
};
IPV4结构体
struct sockaddr_in {sa_family_t sin_family;   // 地址族(address family),通常是 AF_INET,表示使用 IPv4 地址in_port_t sin_port;       // 16 位的端口号,需要使用 `htons()` 函数转换为网络字节序struct in_addr sin_addr;  // 存储 IPv4 地址的结构体char sin_zero[8];         // 填充字节,为保持与 `struct sockaddr` 一致,一般设置为 0
};struct in_addr{uint32_t s_addr;}

3.2 框架搭建

3.2.1 client

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h>    //POSIX.1不需要包含,一些旧版本(BSD)需要包含
#include <sys/socket.h>    
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <string.h>
#include <strings.h>int main(int argc, char const *argv[])
{int sockfd;//初始化网络结构体struct sockaddr_in XXX; ......//1.创建套接字socket()...//客户端绑定端口,客户端在sendto发送数据的时候,操作系统会随机配置一个端口给客户端,bind一般不用#if COND_COMPILLE  ...bind()	...#endifwhile(1){//2.通信...sendto()   //发送数据...recvfrom()   //阻塞接收...}//3.关闭套接字close(sockfd);return 0;
}

3.2.2 server

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h>
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <string.h>int main(int argc, char const *argv[])
{int sockfd; //初始化网络结构体struct sockaddr_in XXX;......//1.创建套接字socket()...//2.绑定端口,用于接收数据bind()...char readBuf[BUF_SIZE] = {0};while(1){//3.数据处理...recvfrom()   //阻塞接收数据...sendto()     //做出响应...}//4.关闭套接字close(sockfd);return 0;
}

3.3 服务端和客户端编写

3.3.1 client_udp.c

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h>
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <string.h>
#include <strings.h>#define BUF_SIZE 256
#define COND_COMPILE 0	
#define QUIT_FLAG "quit"int main(int argc, char const *argv[])
{if(argc !=3 ){printf("input para is incorrent\n");exit(1);}//1.创建套接字int sockfd;//初始化网络结构体struct sockaddr_in serveraddr; socklen_t addrlen = sizeof(serveraddr);bzero(&serveraddr, addrlen);serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = inet_addr(argv[1]);serveraddr.sin_port = htons(atoi(argv[2]));if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){perror("fail to socket");exit(1);}
//客户端绑定端口,一般不用#if COND_COMPILLE  struct sockaddr_in clientaddr;clientaddr.sin_family = AF_INET;clientaddr.sin_addr.s_addr = inet_addr(argv[3]); clientaddr.sin_port = htons(atoi(argv[4])); if(bind(sockfd, (struct sockaddr *)&clientaddr, addrlen) < 0){perror("fail to bind");exit(1);}#endifchar readBuf[BUF_SIZE] = {0};char writeBuf[BUF_SIZE] = {0};while(1){//3.通信fgets(writeBuf, BUF_SIZE-1, stdin);size_t len = strlen(writeBuf);writeBuf[len-1] = '\0';if(sendto(sockfd, writeBuf, (len-1), 0, (struct sockaddr*)&serveraddr, sizeof(serveraddr))==-1){perror("sendto");exit(1);}printf("send complete\n");if(!strncasecmp(writeBuf, QUIT_FLAG, strlen(QUIT_FLAG))){printf("the client exit\n");break;}if(recvfrom(sockfd, readBuf, BUF_SIZE, 0,(struct sockaddr*)&serveraddr, &addrlen)==-1){perror("recvfrom");exit(1);}printf("%s\n",readBuf);bzero(readBuf, BUF_SIZE);bzero(writeBuf, BUF_SIZE);}//关闭套接字close(sockfd);return 0;
}

3.3.2 sever_udp.c

#include <stdio.h> 
#include <stdlib.h> 
#include <sys/types.h>
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <string.h>#define HOST_PORT 5001
#define BUF_SIZE 256
#define QUIT_FLAG "QUIT"
#define RESP ",RESP"
int main(int argc, char const *argv[])
{int sockfd; //初始化网络结构体struct sockaddr_in serveraddr,cin;socklen_t addrlen = sizeof(cin);bzero(&serveraddr, sizeof(serveraddr));serveraddr.sin_family = AF_INET;serveraddr.sin_addr.s_addr = INADDR_ANY;serveraddr.sin_port = htons(HOST_PORT);//1.创建套接字if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){perror("fail to socket");exit(1);}//2.绑定端口,用于接收数据if(bind(sockfd, (struct sockaddr *)&serveraddr, addrlen) < 0){perror("fail to bind");exit(1);}char readBuf[BUF_SIZE] = {0};while(1){//3.数据处理if(recvfrom(sockfd, readBuf, BUF_SIZE, 0, (struct sockaddr*)&cin, &addrlen)==-1){perror("recvform");exit(0);}printf("the client port: %d, IP: %s\n", ntohs(cin.sin_port), inet_ntoa(cin.sin_addr));printf("readBuf: %s\n", readBuf);if(!strncasecmp(readBuf, QUIT_FLAG, strlen(QUIT_FLAG))){printf("the client exit\n");break;}strncat(readBuf, RESP, strlen(RESP));if(sendto(sockfd, readBuf, BUF_SIZE, 0, (struct sockaddr*)&cin, addrlen)==-1){perror("sendto");exit(1);}printf("send complete\n");}close(sockfd);return 0;
}

3.3.3 终端结果

在这里插入图片描述

4.总结

这篇文章着重在UDP实操上,概念上涉及的不是很多。
文章有错误请指出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/57377.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

转置卷积的一些理解

转置卷积 当图像输入到卷积网络中&#xff0c;最终生成的特征图的宽高会减小 在语义分割中标签和原始图像大小一致&#xff0c;若输出宽高减小&#xff0c;不利于标签比对 于是使用转置卷积将图像宽高还原 在卷积的时候&#xff0c;通常输入大于输出&#xff0c;可根据输入大小…

【Linux】waitpid函数 及其 非阻塞等待和阻塞等待

父进程等待子进程结束可以通过两种方式实现&#xff1a;阻塞等待和非阻塞等待。这两种方式各有优缺点&#xff0c;适用于不同的场景。 简单来说&#xff1a; 阻塞等待&#xff1a;先等你&#xff0c;我再继续 非阻塞等待&#xff1a;不等你&#xff0c;我继续做自己的事&…

使用Python实现某易云音乐歌曲下载

前言 在这篇文章中,我们将探讨如何通过Python结合JavaScript代码来逆向网易云音乐的API接口,以获取并下载指定歌曲。请注意,本文仅用于技术学习与交流目的,实际使用时请遵守相关法律法规及服务条款。 目标网站 1. 准备工作 首先,我们需要安装一些必要的库: execjs:用…

NVIDIA RTX 5080移动版GPU真身首曝!全系要用GDDR7

英伟达下一代移动版GPU的神秘面纱似乎正在揭开&#xff0c;Moore’s Law is Dead的最新视频首次曝光了疑似RTX 5080移动版GPU的工程样品照片。 这款工程样品印有N22W-ES-A1&#xff0c;与Clevo的下一代笔记本主板规格表相匹配&#xff0c;表明该芯片确实基于NVIDIA的下一代芯片…

java 提示 避免用Apache Beanutils进行属性的copy。

避免用Apache Beanutils进行属性的copy。 Inspection info: 避免用Apache Beanutils进行属性的copy。 说明&#xff1a;Apache BeanUtils性能较差&#xff0c;可以使用其他方案比如Spring BeanUtils, Cglib BeanCopier。 TestObject a new TestObject(); TestObject b new Te…

Cadence元件A属性和B属性相互覆盖

最近在使用第三方插件集成到Cadence,协助导出BOM到平台上&#xff0c;方便对BOM进行管理和修改&#xff0c;结果因为属性A和属性B不相同&#xff0c;导致导出的BOM错误。如下图&#xff1a; ​​ 本来我们需要导出Q12&#xff0c;结果给我们导出了Q13&#xff0c;或者反之&…

SpringBoot实现的高效民宿预订平台

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

AWD的复现

学习awd的相关资料&#xff1a;速成AWD并获奖的学习方法和思考记录- Track 知识社区 - 掌控安全在线教育 - Powered by 掌控者&#xff08;包含使用脚本去批量修改密码&#xff09; 在复现之前去了解了以下AWD的相关脚本 资料&#xff1a;AWD批量攻击脚本使用教程-CSDN博客 …

13_渲染器的设计

目录 渲染器与响应式系统的结合渲染器的基本概念自定义渲染器 渲染器与响应式系统的结合 渲染器与响应式系统是相辅相成的&#xff0c;渲染器负责将响应式系统中的响应式数据渲染到视图中&#xff0c;而响应式系统则负责监听数据的变化并通知渲染器进行更新。 渲染器在浏览器…

大数据-184 Elasticsearch - 原理剖析 - DocValues 机制原理 压缩与禁用

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff08;已更完&#xff09;HDFS&#xff08;已更完&#xff09;MapReduce&#xff08;已更完&am…

在 Docker 中搭建 PostgreSQL16 主从同步环境

1. 环境搭建 本文介绍了如何在同一台机器上使用 Docker 容器搭建 PostgreSQL 的主从同步环境。通过创建互联网络和配置主库及从库&#xff0c;详细讲解了数据库初始化、角色创建、数据同步和验证步骤。主要步骤包括设置主库的连接信息、创建用于复制的角色、使用 pg_basebacku…

成都跃享未来教育咨询有限公司抖音小店新生态

在数字化浪潮席卷全球的今天&#xff0c;教育行业正经历着前所未有的变革与升级。作为一座历史悠久而又充满活力的城市&#xff0c;成都凭借其深厚的文化底蕴和前瞻性的发展眼光&#xff0c;孕育了众多创新型企业。其中&#xff0c;成都跃享未来教育咨询有限公司&#xff08;以…

计算机专业大学四年的学习路线(非常详细),零基础入门到精通,看这一篇就够了

前言 许多学子选择踏上计算机这条充满挑战与机遇的道路。但在大学四年中&#xff0c;如何规划自己的学习路线&#xff0c;才能在毕业时脱颖而出&#xff0c;成为行业的佼佼者呢&#xff1f; 第一学年&#xff1a;基础知识的奠基 1.1 课程安排 在大学的第一年&#xff0c;重…

spark:Structured Streaming介绍

文章目录 1. Structured Streaming介绍1.1 实时计算和离线计算1.1.1 实时计算1.1.2 离线计算 1.2 有界和无界数据 2. 简单使用3. 编程模型4. 数据处理流程4.1 读取数据Source4.1.1 文件数据处理 4.2 计算操作 Operation4.3 数据输出 Sink4.3.1 输出模式4.3.2 指定输出位置4.3.3…

JVM篇(运行时数据区(实战课程学习总结)

目录 学习前言 一、运行时数据区 1. JVM运行时数据区规范 2. Hotspot运行时数据区 3. 分配JVM内存空间 分配堆的大小 分配方法区的大小 分配线程空间的大小 二、程序计数器 1. 作用 2. 存储的数据 3. 异常 三、Java虚拟机栈 1. 栈帧 1.1. 局部变量表 存储内容 …

【已解决】C# NPOI如何在Excel文本中增加下拉框

前言 上图&#xff01; 解决方法 直接上代码&#xff01;&#xff01;&#xff01;&#xff01;综合了各个大佬的自己修改了一下&#xff01;可以直接规定在任意单元格进行设置。 核心代码方法块 #region Excel增加下拉框/// <summary>/// 增加下拉框选项/// </s…

12. 命令行

Hyperf 的命令行默认由 hyperf/command 组件提供&#xff0c;而该组件本身也是基于 symfony/console 的抽象。 一、安装 通常来说该组件会默认存在&#xff0c;但如果您希望用于非 Hyperf 项目&#xff0c;也可通过下面的命令依赖 hyperf/command 组件。 composer require hype…

使用 Spring 框架构建 MVC 应用程序:初学者教程

Spring Framework 是一个功能强大、功能丰富且设计精良的 Java 平台框架。它提供了一系列编程和配置模型&#xff0c;旨在简化和精简 Java 中健壮且可测试的应用程序的开发过程。 人们常说 Java 太复杂了&#xff0c;构建简单的应用程序需要很长时间。尽管如此&#xff0c;Jav…

Unity/C#使用EPPlus读取和写入Excel

简介&#xff1a;本篇使用EPPlus来将数据写入Excel&#xff0c;如果需要使用NPOI那可以阅读我之前文档使用NPOI创建及写入数据_npoi 模板 写数据-CSDN博客 一、安装EPPlus 这里使用 .unitypackage 文件形式安装 1.1下载NuGetForUnity.unitypackage github进行搜索下载 下载…

vscode设置特定扩展名文件的打开编码格式

用vscode 编辑c语言或者Verilog代码, 由于其它开发工具的文件编码格式无法修改,默认只能是gb2312, 与我们国内奉行的统一 utf8 不一致. 所以只能是更改特殊文件的打开方式. 配置方式如下. 关键配置如下: {"git.openRepositoryInParentFolders": "never",…