UDP编程详解
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客户端流程
- 创建socket:socket()
- 通信:sendto() & recvfrom()
- 关闭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服务器流程
- 创建socket:socket()
- 将创建的socket绑定到一个IP地址和端口号上:bind()
- 等待接收数据报,处理完成后将结果返回到客户端:recvfrom() & sendto(). recvfrom()会阻塞住等待接收消息
- 关闭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;
}
参考文献
本文作者: CrazyCatJack
本文链接: https://www.cnblogs.com/CrazyCatJack/p/14408893.html
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
关注博主:如果您觉得该文章对您有帮助,可以点击文章右下角推荐一下,您的支持将成为我最大的动力!
UDP编程详解的更多相关文章
- Linux的SOCKET编程详解(转)
Linux的SOCKET编程详解 1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系 ...
- 【ARM-Linux开发】Linux的SOCKET编程详解
Linux的SOCKET编程详解 1. 网络中进程之间如何通信 进 程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系 ...
- ORACLE PL/SQL编程详解
ORACLE PL/SQL编程详解 编程详解 SQL语言只是访问.操作数据库的语言,并不是一种具有流程控制的程序设计语言,而只有程序设计语言才能用于应用软件的开发.PL /SQL是一种高级数据库程序设 ...
- ip头、tcp头、udp头详解及定义,结合Wireshark抓包看实际情况
公司的同事们在分析网页加载慢的问题,忽然使用到了Wireshark工具,我就像发现新大陆一样好奇,赶紧看了看,顺便复习了一下相关协议.上学时学的忘的差不多了,汗颜啊! 报文封装整体结构 mac帧头定义 ...
- Linux串口编程详解(转)
串口本身,标准和硬件 † 串口是计算机上的串行通讯的物理接口.计算机历史上,串口曾经被广泛用于连接计算机和终端设备和各种外部设备.虽然以太网接口和USB接口也是以一个串行流进行数据传送的,但是串口连接 ...
- [强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!)
原文:[强烈推荐]ORACLE PL/SQL编程详解之七:程序包的创建与应用(聪明在于学习,天才在于积累!) [强烈推荐]ORACLE PL/SQL编程详解之七: 程序包的创建与应用(聪明在于学习,天 ...
- [推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆)
原文:[推荐]ORACLE PL/SQL编程详解之三:PL/SQL流程控制语句(不给规则,不成方圆) [推荐]ORACLE PL/SQL编程详解之三: PL/SQL流程控制语句(不给规则,不成方圆) ...
- 【强烈强烈推荐】《ORACLE PL/SQL编程详解》全原创(共八篇)--系列文章导航
原文:[强烈强烈推荐]<ORACLE PL/SQL编程详解>全原创(共八篇)--系列文章导航 <ORACLE PL/SQL编程详解> 系列文章目录导航 ——通过知识共享树立个人 ...
- [推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下)
原文:[推荐]ORACLE PL/SQL编程详解之一:PL/SQL 程序设计简介(千里之行,始于足下) [推荐]ORACLE PL/SQL编程详解之一: PL/SQL 程序设计简介(千里之行,始于足下 ...
随机推荐
- TCP/IP__TCP协议常用协议默认端口号
- 最好的IDEA debug长文?看完我佛了
前言 你好,我是A哥(YourBatman). 最近写了几篇IntelliJ IDEA系列的文章,反响蛮好.我想了下,因为并非是分享什么破解方法.推荐插件.主题这种蛋炒饭式哗众取宠的文章,而是真实对工 ...
- Codeforces Round #594 (Div. 2) D1 - The World Is Just a Programming Task
思路:枚举换的位置i,j 然后我们要先判断改序列能否完全匹配 如果可以 那我们就需要把差值最大的位置换过来 然后直接判断就行
- hdu2825 Wireless Password(AC自动机+状压dp)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission ...
- 迪杰斯特拉+拆点 Deliver the Cake - HDU 6805
题意: t组输入,给你n个点m条边.你需要输出从s点到t点的最短距离,然后是m条边,每条边输入信息为: a,b,c 表示从a点到b点的一个无向边长度为c 每一个点会有一个属性L.R或M 如果a和b一个 ...
- Codeforces 1144F Graph Without Long Directed Paths DFS染色
题意: 输入一张有向图,无自回路和重边,判断能否将它变为有向图,使得图中任意一条路径长度都小于2. 如果可以,按照输入的边的顺序输出构造的每条边的方向,构造的边与输入的方向一致就输出1,否则输出0. ...
- [CodeForces-629A 用阶乘会爆掉
题意: 给你一个n*n的蛋糕,如果某个位置是'C'那就代表这是一个巧克力块,否则就不是.如果某两个巧克力块在同一行或同一列,那么这个家庭的幸福值就会加1,问你这个家庭的幸福值最大是多少 Input 3 ...
- hdu5317 RGCDQ
Problem Description Mr. Hdu is interested in Greatest Common Divisor (GCD). He wants to find more an ...
- python代理池的构建3——爬取代理ip
上篇博客地址:python代理池的构建2--代理ip是否可用的处理和检查 一.基础爬虫模块(Base_spider.py) #-*-coding:utf-8-*- ''' 目标: 实现可以指定不同UR ...
- 自动生成requirements.txt
Python 自动生成当前项目的requirements.txt 通常我们开发一个python项目时都会用conda 或者 virtualenv 等虚拟环境管理工具来创建一个虚拟环境,在这个虚拟环境中 ...