【北京迅为】iTOP-4412全能版使用手册-第三十三章 网络通信-UDP套接字

iTOP-4412全能版采用四核Cortex-A9,主频为1.4GHz-1.6GHz,配备S5M8767 电源管理,集成USB HUB,选用高品质板对板连接器稳定可靠,大厂生产,做工精良。接口一应俱全,开发更简单,搭载全网通4G、支持WIFI、蓝牙、陀螺仪、CAN总线、RS485总线、500万摄像头等模块,稳定运行Android 4.0.3/Android 4.4操作,系统通用Linux-3.0.15+Qt操作系统(QT支持5.7版本),Ubuntu版本:12.04,接口智能分配 方便好用。


第三十三章 网络通信-UDP套接字

上一章讲了基于 TCP 的 socket 编程,这一章我讲解一下基于 UDP 的 socket 编程, UDP 是用户数据报协议,它是一种无连接的传输层协议,提供面向事物的简单不可靠信息传送服务,所以在一些网络质量不满意的环境下,UDP 协议数据包丢失会比较严重,会造成数据的丢失。UDP 的特点是它不属于连接型协议,所以资源消耗小。处理速度快的优点,所以通常音频,视频和普通数据在传送时使用 UDP 较多,因为它们即使偶尔丢失一两个数据包, 也不会对接收结果产生太大影响。

本章配套视频为:

"视频 19 网络通信-套接字 UDP"

33.1 UDP通信简介

UDP 的通信框图如下图所示:

从上图可以看到基于 UDP 通信的程序也是由服务器和客户端组成。与 TCP 的服务器不同,UDP 的服务器不需要 listen 和 accept 函数,客户端不需要 connect 函数。

33.2 服务器端程序

下面通过一个例子来了解一下 UDP 的应用程序,首先来看下服务器(server)端的程序server.c:

复制代码
#include <stdio.h> 
#include <string.h> 
#include <sys/socket.h>
#include <netinet/in.h>

int main(int argc, char **argv)
{
 	int n;
 	char recvline[1024] = {0};

 	int sockfd;
 	struct sockaddr_in servaddr;

 	/* 创建一个 UDP 连接的 socket */
 	sockfd = socket(PF_INET, SOCK_DGRAM, 0);

 	/* 变量 servaddr 清零 */
 	bzero(&servaddr, sizeof(servaddr));
 	servaddr.sin_family = AF_INET;
 	servaddr.sin_addr.s_addr = htonl(INADDR_ANY); 
 	servaddr.sin_port = htons(50001);

 	/* 绑定 servaddr 到创建的 socket 上 */
 	bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

 	/* 接收客户端发送的数据 */
 	recvfrom(sockfd, recvline, 1024, 0, NULL, NULL);
 	printf("%s\n", recvline);

 	/* 关闭 socket 连接 */
 	close(sockfd);
}

上面的代码和前面一章的 TCP 的服务器程序差不多,首先也是定义一些变量,然后调用socket 函数创建一个套接字,这里 socket 函数的第二个参数是 SOCK_DGRAM,即用户数据报,也就是创建的 UDP 连接,然后调用 bzero 函数清空变量 servaddr 的值,然后设置servaddr 结构的值,接着调用 bind 绑定函数,然后调用 recvfrom 函数直接接收数据,在这个过程中我们没有调用 listen 和 accept 函数。

33.3 客户端程序

下面来看看客户端(client)的程序 client.c:

复制代码
#include <stdio.h>
#include <string.h> 
#include <sys/socket.h> 
#include <netinet/in.h>

int main(int argc, char **argv)
{
 	int sockfd;
 	struct sockaddr_in servaddr;

 	if(argc != 2)
 	{
 		printf("usgae: ./client [ip]\n");
 		return -1;
 	}


 	/* 创建一个 UDP 的 socket 连接 */
 	sockfd = socket(PF_INET, SOCK_DGRAM, 0);

 	/* 变量 servaddr 清零 */
 	bzero(&servaddr, sizeof(servaddr));
 	servaddr.sin_family = AF_INET;
 	servaddr.sin_port = htons(50001);
 	servaddr.sin_addr.s_addr = inet_addr(argv[1]);

 	char sendline[100];
 	sprintf(sendline, "Hello, world!");

 	/*	发送数据 */
 	sendto(sockfd, sendline, strlen(sendline), 0, (struct sockaddr *)&servaddr, sizeof(servaddr));

 	/* 关闭 socket 连接 */
 	close(sockfd);

 	return 1;
}

客户端(client)的程序首先是定义一些使用的变量,然后也是调用 socket 函数创建一个套接字,socket 函数的第二个参数是 SOCK_DGRAM,即用户数据报,也就是 UDP 连接,然后调用 bzero 函数把 servaddr 结构的变量清零,然后设置 servaddr 结构变量的值, 然后调用 sendto 发送函数,这里客户端程序没有调用 bind 函数和 connect 函数。现在使用命令

gcc -o server server.c

执行结果如下图。

使用命令 arm-none-linux-gnueabi-gcc -o client client.c 编译 client.c,执行结果如下图。

把生成的 client 拷贝到 NFS 文件系统的 bin 目录下,如下图。

然后在虚拟机 Ubuntu 上运行 server 程序,如下图。

在 iTOP-4412 开发板上运行 client 程序,如下图。

执行结果如下图。

现在看下虚拟机 Ubuntu 的 server 程序的输出,如下图。

可以看到 server 程序输出"Hello,word",上面的打印信息就是 client 发送的数据。至此基于 UDP 的 socket 通讯就实现了。

相关推荐
2401_892070981 天前
【Linux C++ 日志系统实战】LogFile 日志文件管理核心:滚动策略、线程安全与方法全解析
linux·c++·日志系统·日志滚动
fie88891 天前
基于51单片机的航模遥控器6通道接收机程序
单片机·嵌入式硬件·51单片机
lwx9148521 天前
Linux-Shell算术运算
linux·运维·服务器
somi71 天前
ARM-驱动-02-Linux 内核开发环境搭建与编译
linux·运维·arm开发
bu_shuo1 天前
嵌入式硬件工程师VS单板硬件工程师
嵌入式硬件·电子工程师·单板硬件
llilian_161 天前
选择北斗导航卫星信号模拟器注意事项总结 北斗导航卫星模拟器 北斗导航信号模拟器
功能测试·单片机·嵌入式硬件·测试工具·51单片机·硬件工程
双份浓缩馥芮白1 天前
【Docker】Linux 迁移 docker 目录(软链接)
linux·docker
Yyq130208696821 天前
MH2457,‌国产 32 位屏驱 MCU‌芯片,支持‌1080P 高清显示‌与‌以太网通信‌,广泛应用于两轮车仪表盘及工控屏等领域
单片机·嵌入式硬件
黄昏晓x1 天前
Linux ---- UDP和TCP
linux·tcp/ip·udp
路溪非溪1 天前
Linux驱动开发中的常用接口总结(一)
linux·运维·驱动开发