UDP与TCP的不同之处是:他的通信不需要建立连接的过程。中文名称用户数据报协议。时OSI参考模型中一种无连接的传输层协议。提供面向事务的简单不可靠信息传送服务,UDP在IP报文中的协议号是17.与TCP(传输控制协议)一样,UDP协议直接位于IP(网际协议)协议的顶层,根据TCP/IP参考模型,UDP和TCP都属于传输层协议。UDP协议的主要作用是将数据压缩成数据包的形式,一个典型的数据包就是一个二进制数据的传输单位。每一个数据包的前8个字节用来包含报头信息,剩余字节则用来包含具体的传输数据。

报文格式

源端口(2字节)+目的端口(2字节)+长度(2字节)+校验和(2字节)+数据

通信过程

UDP协议较TCP简单很多,减少了TCP的握手、确认、窗口、重传、拥塞控制等机制,UDP是一个无状态的传输协议。UDP客户端在发送数据时并不判断主机是否可达,服务器是否开启等问题,他不能确定数据是否成功到达服务器,他只是将数据简单的封了一个包,之后就丢出去了。

UDP客户端流程

  1. 创建socket:socket()
  2. 通信:sendto() & recvfrom()
  3. 关闭socket:closesocket()

UDP客户端编码

void udpclient(int argc, char **argv)
{
int sock, port, count;
struct hostent *host;
struct sockaddr_in server_addr;
const char *url; if (argc < 3)
{
rt_kprintf("Usage: udpclient URL PORT [COUNT = 10]\n");
rt_kprintf("Like: tcpclient 192.168.12.44 5000\n");
return ;
} url = argv[1];
port = strtoul(argv[2], 0, 10); if (argc > 3)
count = strtoul(argv[3], 0, 10);
else
count = 10; /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */
host = (struct hostent *) gethostbyname(url); /* 创建一个socket,类型是SOCK_DGRAM,UDP类型 */
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
rt_kprintf("Socket error\n");
return;
} /* 初始化预连接的服务端地址 */
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); /* 总计发送count次数据 */
while (count)
{
/* 发送数据到服务远端 */
sendto(sock, send_data, strlen(send_data), 0,
(struct sockaddr *)&server_addr, sizeof(struct sockaddr)); /* 线程休眠一段时间 */
rt_thread_delay(50); /* 计数值减一 */
count --;
} /* 关闭这个socket */
closesocket(sock);
}

UDP服务器流程

  1. 创建socket:socket()
  2. 将创建的socket绑定到一个IP地址和端口号上:bind()
  3. 等待接收数据报,处理完成后将结果返回到客户端:recvfrom() & sendto(). recvfrom()会阻塞住等待接收消息
  4. 关闭socket:close()

UDP服务器编码

static void udpserv(int argc, char **argv)
{
int sock;
int bytes_read;
char *recv_data;
socklen_t addr_len;
struct sockaddr_in server_addr, client_addr; /* 分配接收用的数据缓冲 */
recv_data = rt_malloc(BUFSZ);
if (recv_data == RT_NULL)
{
/* 分配内存失败,返回 */
rt_kprintf("No memory\n");
return;
} /* 创建一个socket,类型是SOCK_DGRAM,UDP类型 */
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
rt_kprintf("Socket error\n"); /* 释放接收用的数据缓冲 */
rt_free(recv_data);
return;
} /* 初始化服务端地址 */
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5000);
server_addr.sin_addr.s_addr = INADDR_ANY;
rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); /* 绑定socket到服务端地址 */
if (bind(sock, (struct sockaddr *)&server_addr,
sizeof(struct sockaddr)) == -1)
{
/* 绑定地址失败 */
rt_kprintf("Bind error\n"); /* 释放接收用的数据缓冲 */
rt_free(recv_data);
return;
} addr_len = sizeof(struct sockaddr);
rt_kprintf("UDPServer Waiting for client on port 5000...\n"); while (1)
{
/* 从sock中收取最大BUFSZ - 1字节数据 */
bytes_read = recvfrom(sock, recv_data, BUFSZ - 1, 0,
(struct sockaddr *)&client_addr, &addr_len);
/* UDP不同于TCP,它基本不会出现收取的数据失败的情况,除非设置了超时等待 */ recv_data[bytes_read] = '\0'; /* 把末端清零 */ /* 输出接收的数据 */
rt_kprintf("\n(%s , %d) said : ", inet_ntoa(client_addr.sin_addr),
ntohs(client_addr.sin_port));
rt_kprintf("%s", recv_data); /* 如果接收数据是exit,退出 */
if (strcmp(recv_data, "exit") == 0)
{
closesocket(sock); /* 释放接收用的数据缓冲 */
rt_free(recv_data);
break;
}
} return;
}

参考文献

  1. RT-Thread视频中心内核入门
  2. RT-Thread文档中心

本文作者: CrazyCatJack

本文链接: https://www.cnblogs.com/CrazyCatJack/p/14408893.html

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

关注博主:如果您觉得该文章对您有帮助,可以点击文章右下角推荐一下,您的支持将成为我最大的动力!


UDP编程详解的更多相关文章

  1. Linux的SOCKET编程详解(转)

    Linux的SOCKET编程详解 1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系 ...

  2. 【ARM-Linux开发】Linux的SOCKET编程详解

    Linux的SOCKET编程详解 1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系 ...

  3. ORACLE PL/SQL编程详解

    ORACLE PL/SQL编程详解 编程详解 SQL语言只是访问.操作数据库的语言,并不是一种具有流程控制的程序设计语言,而只有程序设计语言才能用于应用软件的开发.PL /SQL是一种高级数据库程序设 ...

  4. ip头、tcp头、udp头详解及定义,结合Wireshark抓包看实际情况

    公司的同事们在分析网页加载慢的问题,忽然使用到了Wireshark工具,我就像发现新大陆一样好奇,赶紧看了看,顺便复习了一下相关协议.上学时学的忘的差不多了,汗颜啊! 报文封装整体结构 mac帧头定义 ...

  5. Linux串口编程详解(转)

    串口本身,标准和硬件 † 串口是计算机上的串行通讯的物理接口.计算机历史上,串口曾经被广泛用于连接计算机和终端设备和各种外部设备.虽然以太网接口和USB接口也是以一个串行流进行数据传送的,但是串口连接 ...

  6. [强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!)

    原文:[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!) [强烈推荐]ORACLE PL/SQL编程详解之七: 程序包的创建与应用(聪明在于学习,天 ...

  7. [推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆)

    原文:[推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆) [推荐]ORACLE PL/SQL编程详解之三: PL/SQL流程控制语句(不给规则,不成方圆) ...

  8. 【强烈强烈推荐】《ORACLE PL/SQL编程详解》全原创(共八篇)--系列文章导航

    原文:[强烈强烈推荐]<ORACLE PL/SQL编程详解>全原创(共八篇)--系列文章导航 <ORACLE PL/SQL编程详解> 系列文章目录导航 ——通过知识共享树立个人 ...

  9. [推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下)

    原文:[推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下) [推荐]ORACLE PL/SQL编程详解之一: PL/SQL 程序设计简介(千里之行,始于足下 ...

随机推荐

  1. 网络编程(socket简介)

    socket简介 Python 提供了两个基本的 socket 模块. 第一个是 Socket,它提供了标准的 BSD Sockets API. 第二个是 SocketServer, 它提供了服务器中 ...

  2. python----类,面向对象(封装、继承、多态)(属性,方法)

    什么是对象? 对象是内存中专门用来存储数据的一块区域 对象中可以存放各种数据(数字.代码等) 对象由三部分组成(1,对象标识(id)2,对象类型(type)3,对象的值(value)) 面向对象编程是 ...

  3. CentOS 7 部署redis

    1.下载redis: 地址:http://download.redis.io/releases/: 选择需要下载的版本,然后通过ssh工具导入到centos中,这里放到了/usr/local; 解压文 ...

  4. 二分图最大权匹配问题&&KM算法讲解 && HDU 2255 奔小康赚大钱

    作者:logosG 链接:https://www.cnblogs.com/logosG/p/logos.html (讲解的KM算法,特别厉害!!!) KM算法: 现在我们来考虑另外一个问题:如果每个员 ...

  5. HOJ1867 经理的烦恼

    My Tags   (Edit)   Source : HCPC 2005 Spring   Time limit : 2 sec   Memory limit : 32 M Submitted : ...

  6. rabbitmq常见面试题

    1.使用RabbitMQ有什么好处?1.解耦,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦! 2.异步,将消息写入消息队列,非必要的业务逻辑以异步的方 ...

  7. GitHub Actions 支持 "skip ci" 了

    GitHub Actions 支持 "skip ci" 了 Intro GitHub Actions 作为 GitHub 官方的 CI 支持,很多开源项目已经在使用 Actions ...

  8. 计算机网络 part2

    一.UDP协议 1.概述 UDP提供不可靠的服务,无连接(不存在建立连接的时延),首部开销相对TCP小,没有拥塞控制,提供最大努力交付,面向报文(无论多长的报文UDP也只加一个头部就往下发:TCP面向 ...

  9. HDU4578 Transformation(多标记线段树)题解

    题意: 操作有:\(1\).区间都加\(a\):\(2\).区间都乘\(a\):\(3\).区间都重置成\(a\):\(4\).询问区间幂次和\(\sum_{i=l}^rnum[i]^p(p\in\{ ...

  10. C++模板沉思录

    0 论抽象--前言 故事要从一个看起来非常简单的功能开始: 请计算两个数的和. 如果你对Python很熟悉,你一定会觉得:"哇!这太简单了!",然后写出以下代码: def Plus ...