【网络编程】深入了解UDP协议:快速数据传输的利器

这篇具有很好参考价值的文章主要介绍了【网络编程】深入了解UDP协议:快速数据传输的利器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  • (꒪ꇴ꒪ ),Hello我是祐言QAQ
  • 我的博客主页:C/C++语言,数据结构,Linux基础,ARM开发板,网络编程等领域UP🌍
  • 快上🚘,一起学习,让我们成为一个强大的攻城狮!
  • 送给自己和读者的一句鸡汤🤔:集中起来的意志可以击穿顽石!
  • 作者水平很有限,如果发现错误,请在评论区指正,感谢🙏

        在计算机网络中,UDP(User Datagram Protocol)是一种重要的传输层协议,与TCP(Transmission Control Protocol)一样位于 OSI 模型的传输层。但与TCP不同,UDP提供了一种无连接、轻量级的数据传输方式,适用于需要快速传输数据的应用场景。本文将深入探讨UDP协议的特点、用途以及与TCP的对比。

一、UDP的特点

  1. 无连接性:UDP不需要在通信前建立连接,也不维护连接状态,因此它更加轻量级。这使得UDP适用于实时数据传输,如音频和视频流。

  2. 不可靠性:UDP不提供数据包的可靠性传输。这意味着数据包可能会丢失、重复或无序到达目标。因此,UDP通常用于那些可以容忍一些数据丢失的应用,如实时多媒体流。

  3. 高性能:由于不需要建立连接和维护状态信息,UDP的开销较低,具有较高的性能。这使得它成为一种适用于高吞吐量、低延迟的协议。

  4. 头部小:UDP的头部相对较小,只包含源端口、目标端口、长度和校验和等字段,这有助于减少数据传输时的开销。

  5. 多播和广播:UDP支持多播和广播,可以同时向多个接收方发送数据包,适用于一对多或多对多通信。

二、UDP的用途

        UDP在许多应用中发挥着重要作用,包括但不限于:

  • 实时音视频传输:VoIP电话、视频会议和直播流都使用UDP来传输实时音视频数据,因为它具有低延迟和快速传输的特性。

  • DNS查询:域名系统(DNS)使用UDP来快速查询域名解析。

  • 游戏数据传输:在线游戏经常使用UDP来传输游戏数据,以确保低延迟和实时性。

  • 网络广播:UDP用于发送广播消息,例如局域网内的设备发现和服务广告。

三、UDP实现服务器与客户端相互通信

        在此之前我们已经学习掌握了TCP/IP实现服务器与客户端通信,链接我放这里:

【网络编程】TCP传输控制协议(Transmission Control Protocol)_祐言QAQ的博客-CSDN博客

        那么现在让我们一起来学习一下UDP如何实现通信。

1.UDP服务器与客户端设计思路

【网络编程】深入了解UDP协议:快速数据传输的利器,网络编程,系统编程,网络,网络协议,运维,udp,安全

        不难看出其中与TCP通信有几个不同点:

①套接字类型:

        TCP使用 SOCK_STREAM 表示流式套接字,这意味着它提供面向连接的、可靠的、基于字节流的通信;
        UDP使用 SOCK_DGRAM 表示数据报套接字,这表明它提供无连接的、不可靠的、基于数据报的通信。


②通信流程:

        在TCP中,通信需要经过 listen、accept 和 connect 过程,其中建立连接是必要的;
        在UDP中,通信是无连接的,不需要建立连接,因此不需要进行 listen、accept 和 connect 步骤。


③收发数据的函数:

        在TCP中,通常使用 recv 和 send 函数来进行数据的接收和发送;
        在UDP中,通常使用 recvfrom 和 sendto 函数来进行数据的接收和发送。这些函数需要指定目标地址,因为UDP是无连接的,每个数据包都需要包含目标地址信息。

2.具体实现代码

【网络编程】深入了解UDP协议:快速数据传输的利器,网络编程,系统编程,网络,网络协议,运维,udp,安全

udp_server.c
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <pthread.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

// 定义一个结构体用于存储客户端信息
struct Client
{
	struct sockaddr_in addr; // 客户端地址结构体
	int ser_socket;         // 服务器套接字
};

// 线程函数,用于发送数据
void *send_data(void *arg)
{
	struct Client *cli = (struct Client *)arg;
	char buf[1024];

	while (1)
	{
		scanf("%[^\n]", buf); // 从用户输入读取数据
		while (getchar() != '\n');

		// 发送数据到客户端
		sendto(cli->ser_socket, buf, strlen(buf), 0, (struct sockaddr *)&(cli->addr), sizeof(cli->addr));
	}
}

int main(int argc, char const *argv[])
{
	if (argc != 2)
	{
		printf("./server <port>\n");
		return -1;
	}

	// 创建套接字socket
	int ser_socket = socket(AF_INET, SOCK_DGRAM, 0);
	if (ser_socket == -1)
	{
		perror("socket");
		return -1;
	}

	// 设置套接字属性,SO_REUSEADDR 允许地址端口重用
	int on = 1;
	if (setsockopt(ser_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1)
	{
		perror("setsockopt");
		return -1;
	}

	// 初始化地址结构体
    struct sockaddr_in addr;
	addr.sin_family = AF_INET;   							// 地址簇
	addr.sin_port = atoi(argv[1]);							// 端口(一般以传参的传进来)
	// addr.sin_addr.s_addr = inet_addr("192.168.1.128");	// IP地址
	addr.sin_addr.s_addr = htonl(INADDR_ANY);				// 用特殊的"0.0.0.0"这个IP来绑定本机IP地址

	// bind 绑定IP跟PORT
	int b = bind(ser_socket, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
	if(b == -1)
	{
		perror("bind");
		return -1;
	}
	printf("绑定成功\n");

	struct sockaddr_in c_addr;		// IPV4地址结构体
	int addrlen = sizeof(c_addr);
	char buf[1024];

	// 接收客户端的第一条消息
	recvfrom(ser_socket, buf, sizeof(buf), 0, (struct sockaddr *)&c_addr, &addrlen);
	printf("[%s] [%d]:%s\n", inet_ntoa(c_addr.sin_addr), c_addr.sin_port, buf);

	struct Client cli;
	cli.addr = c_addr;
	cli.ser_socket = ser_socket;

	// 创建一个线程用来发送数据
	pthread_t pid;
	pthread_create(&pid, NULL, send_data, &cli);

	// 接收/发送数据 recvfrom/sendto
	while(1)
	{
		bzero(buf, sizeof(buf));
		// 每接收一条客户端发送的信息,保存一次客户端的IP+PORT
		recvfrom(ser_socket, buf, sizeof(buf), 0, (struct sockaddr *)&c_addr, &addrlen);
		// 第一次接收,创建线程发送数据,将套接字,对方的IP地址传递给线程任务函数
		printf("[%s] [%d]:%s\n", inet_ntoa(c_addr.sin_addr), c_addr.sin_port, buf);
	}

	// 关闭套接字close
	close(ser_socket);

	return 0;
}
udp_client.c
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <pthread.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

// 线程函数,用于接收数据
void *recv_data(void *arg)
{
	int cli_socket = *(int *)arg;
	struct sockaddr_in c_addr;
	int addrlen = sizeof(c_addr);
	char buf[1024];

	while(1)
	{
		bzero(buf, sizeof(buf));
		// 每接收一条客户端发送的信息,保存一次客户端的IP+PORT
		recvfrom(cli_socket, buf, sizeof(buf), 0, (struct sockaddr *)&c_addr, &addrlen);
		printf("[%s] [%d]:%s\n", inet_ntoa(c_addr.sin_addr), c_addr.sin_port, buf);
	}
}

int main(int argc, char const *argv[])
{
	if (argc != 3)
	{
		printf("./client <ip> <port>\n");
		return -1;
	}

	// (1) 创建套接字socket
	int cli_socket = socket(AF_INET, SOCK_DGRAM, 0);
	if (cli_socket == -1)
	{
		perror("socket");
		return -1;
	}

	// (2) 初始化地址结构体(服务器的)
	struct sockaddr_in addr;
	addr.sin_family = AF_INET;   				// 地址簇
	addr.sin_port = atoi(argv[2]);				// 服务器端的端口(一般以传参的传进来)
	addr.sin_addr.s_addr = inet_addr(argv[1]);	// 服务器端的IP地址(一般以传参的传进来)

	// 先发一条上线的消息给server
	char buf[1024] = "on line";
	sendto(cli_socket, buf, strlen(buf), 0, (struct sockaddr *)&addr, sizeof(addr));

	// 创建线程用来接收数据
	pthread_t pid;
	pthread_create(&pid, NULL, recv_data, &cli_socket);

	// (3) 发送数据
	while(1)
	{
		scanf("%[^\n]", buf); // 从用户输入读取数据
		while(getchar()!='\n');

		// 发送数据buf
		sendto(cli_socket, buf, strlen(buf), 0, (struct sockaddr *)&addr, sizeof(addr));
	}

	// (5) 关闭套接字close
	close(cli_socket);

	return 0;
}

四、UDP套接字获取和设置

        在UDP套接字编程中,你可以使用 getsockoptsetsockopt 函数来获取和设置套接字的属性。以下是一些常见的UDP套接字属性以及如何使用这两个函数来处理它们:

获取套接字属性(使用 getsockopt 函数):

  1. SO_RCVBUF 和 SO_SNDBUF

    • 功能:获取套接字的接收缓冲区和发送缓冲区的大小。
    • 示例代码:
      int buffer_size;
      socklen_t optlen = sizeof(buffer_size);
      getsockopt(socket_fd, SOL_SOCKET, SO_RCVBUF, &buffer_size, &optlen);
      // 现在 buffer_size 中包含接收缓冲区的大小
      
  2. SO_RCVTIMEO 和 SO_SNDTIMEO

    • 功能:获取套接字的接收超时时间和发送超时时间。
    • 示例代码:
      struct timeval timeout;
      socklen_t optlen = sizeof(timeout);
      getsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, &optlen);
      // 现在 timeout 中包含接收超时时间
      

设置套接字属性(使用 setsockopt 函数):

  1. SO_RCVBUF 和 SO_SNDBUF

    • 功能:设置套接字的接收缓冲区和发送缓冲区的大小。
    • 示例代码:
      int buffer_size = 8192; // 设置缓冲区大小
      setsockopt(socket_fd, SOL_SOCKET, SO_RCVBUF, &buffer_size, sizeof(buffer_size));
      
  2. SO_RCVTIMEO 和 SO_SNDTIMEO

    • 功能:设置套接字的接收超时时间和发送超时时间。
    • 示例代码:
      struct timeval timeout;
      timeout.tv_sec = 5; // 设置超时时间为5秒
      timeout.tv_usec = 0;
      setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
      

        这些是一些常见的UDP套接字属性设置选项。可以根据需要使用 getsockoptsetsockopt 函数来获取和设置套接字的其他属性,具体选项取决于你的应用程序的需求。套接字属性设置允许你自定义套接字的行为,以满足不同的网络通信需求。在上面的服务端与客户端通信中也有用到一些示例。

五、与TCP的对比

UDP和TCP是两种不同的传输协议,它们在以下方面有所不同:

  • 连接性:UDP无连接,TCP面向连接。

  • 可靠性:UDP不提供可靠性传输,TCP提供可靠性传输。

  • 开销:UDP开销较低,TCP开销较高。

  • 适用场景:UDP适用于需要快速传输但可以容忍一些数据丢失的应用,而TCP适用于需要确保数据完整性和可靠性的应用。

六、总结

        UDP协议在网络通信中扮演着重要的角色,尤其是在需要实时性和低延迟的应用中。虽然它不提供可靠性传输,但在正确的应用场景下,UDP是一个强大的工具,能够满足快速数据传输的需求。了解UDP的特点和用途有助于网络工程师更好地选择合适的协议来满足应用程序的需求。

        更多C/C++语言Linux系统数据结构ARM板实战相关文章,关注专栏:

   手撕C语言

            玩转linux

                    脚踢数据结构

                            系统、网络编程

                                     探索C++

                                             6818(ARM)开发板实战文章来源地址https://www.toymoban.com/news/detail-705069.html

📢写在最后

  • 今天的分享就到这啦~
  • 觉得博主写的还不错的烦劳 一键三连喔~
  • 🎉🎉🎉感谢关注🎉🎉🎉

到了这里,关于【网络编程】深入了解UDP协议:快速数据传输的利器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python网络编程之UDP协议

    Hello,大家好。本期来和大家一起学习一下网络编程UDP的相关知识。 ip ip地址:用来在网络中标记一台电脑,在本地局域网上是唯一的。 查看电脑ip地址:ipconfig(win)/ifconfig(linux/mac) 端口 端口:设备与外界通讯交流的出口 一共有65536个(0 - 65535) 端口 知名端口是众所周知的

    2024年02月03日
    浏览(34)
  • 【网络编程】TCP,UDP协议详解

    小亭子正在努力的学习编程,接下来将开启javaEE的学习~~ 分享的文章都是学习的笔记和感悟,如有不妥之处希望大佬们批评指正~~ 同时如果本文对你有帮助的话,烦请点赞关注支持一波, 感激不尽~~   目录 前言 TCP协议 TCP协议特点 TCP协议通信场景 TCP协议的几个重要机制 一、

    2023年04月19日
    浏览(50)
  • [网络编程]UDP协议,基于UDP协议的回显服务器

    目录 1.UDP协议介绍 2.UDP协议在Java中的类 2.1DatagramSocket类 2.2DatagramPacket 3.回显服务器 3.1Sever端  3.2Client端   UDP协议是一种网络协议,它是无连接的,全双工,并且是面向数据报,不可靠的一种协议。 常用于在线视频播放,游戏这种实时性要求比较高的应用。或者无需可靠传输

    2024年01月22日
    浏览(51)
  • Netty网络编程(五):使用UDP协议

    今天我将会给大家介绍如何在netty中使用UDP协议。 UDP( User Datagram Protocol ),也叫用户数据报协议。 UDP 的主要功能和亮点并不在于它引入了什么特性,而在于它忽略的那些特性:不保证消息交付,不保证交付顺序,不跟踪连接状态,不需要拥塞控制。 我们来看一下UDP的数据包

    2023年04月27日
    浏览(54)
  • 【QT网络编程】实现UDP协议通信

    Internet 协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP,User Datagram Protocol)。UDP 为应用程序提供了 一种无需建立连接就可以发送封装的 IP 数据包的方法 。RFC 768 描述了 UDP。 UDP协议根据消息传送模式可以分为: 单播(Unicast)、组播(Multicast)和广播(

    2024年02月02日
    浏览(52)
  • 网络编程-UDP协议(发送数据和接收数据)

    需要了解TCP协议的,可以看往期文章 https://blog.csdn.net/weixin_43860634/article/details/133274701 通过此图,可以了解UDP所在哪一层级中 发送数据 接收数据 运行效果 1、 UDP是面向无连接通信协议 (通俗一点讲,就是不管是否已连接成功,直接发送数据),该特性正好与TCP协议相反,

    2024年02月07日
    浏览(38)
  • Java网络编程 *TCP与UDP协议*

    把分布在 不同地理区域 的具有独立功能的计算机, 通过通信设备与线路 连接起来,由功能完善的软件实现资源共享和信息传递的 系统 简单来说就是把不同地区的计算机通过设备连接起来,实现不同地区之前的数据传输 网络编程 是借助计算机网络,实现我们所写的程序,在不同

    2024年01月16日
    浏览(58)
  • 网络编程——TCP/IP协议族(IP协议、TCP协议和UDP协议……)

    1、IP协议简介 IP协议又称 网际协议 特指为实现在一个相互连接的网络系统上从源地址到目的地传输数据包(互联网数据包)所提供必要功能的协议,是网络层中的协议。 2、特点 不可靠 :它不能保证IP数据包能成功地到达它的目的地,仅提供尽力而为的传输服务 无连接 :IP 并不

    2024年02月13日
    浏览(66)
  • 【从入门到起飞】JavaSE—网络编程三要素,软件架构,UDP协议

    在网络通信协议下,不同计算机上运行的程序,进行的数据传输 简而言之,就是可以把自己电脑上的资料 通过代码 传到其他人的电脑上 (对画质要求不高时使用) 不需要开发客户端,只需要页面+服务端 用户不需要下载,打开浏览器就能用 如果应用过大,用户体验会受到

    2024年02月08日
    浏览(35)
  • Java网络编程之IP,端口号,通信协议(UDP,TCP)

    ① C/S :客户端/服务器 在用户本地需要下载安装客户端程序,在远程有一个服务器端程序。 优点:画面精美,用户体验好 缺点:用户需要下载更新 ② B/S :浏览器/服务器 只需要一个浏览器,用户通过指定网址访问对应的服务器。 优点:不需要开发客户端,只需要页面+服务

    2024年02月03日
    浏览(78)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包