[C++ 网络协议编程] UDP协议

目录

[1. UDP和TCP的区别](#1. UDP和TCP的区别)

[2. UDP的工作原理](#2. UDP的工作原理)

[3. UDP存在数据边界](#3. UDP存在数据边界)

[4. UDP的I/O函数](#4. UDP的I/O函数)

[4.1 sendto函数](#4.1 sendto函数)

[4.2 recvfrom函数](#4.2 recvfrom函数)

[4. 已连接(connected)UDP套接字和未连接(unconnected)UDP套接字](#4. 已连接(connected)UDP套接字和未连接(unconnected)UDP套接字)

[5. UDP的通信流程](#5. UDP的通信流程)

[5.1 服务器端通信流程](#5.1 服务器端通信流程)

[5.2 客户端通信流程](#5.2 客户端通信流程)


1. UDP和TCP的区别

主要区别:

  1. TCP和UDP的主要区别是,TCP具有流控制机制,而UDP没有。
  2. UDP性能比TCP高,在数据量大的情况下,TCP的性能会接近UDP的性能,但无法超过UDP。

TCP比UDP慢的原因主要如下:

  1. 收发数据前后进行的连接设置及清除过程

  2. 收发数据过程中为保证可靠性而添加的流控制

  1. UDP不如TCP可靠,有可能会发生数据的丢失。

2. UDP的工作原理

如图,IP的作用是让数据准确传到主机A,而UDP的最重要的作用就是把数据准确的传到主机A的指定套接字上。

3. UDP存在数据边界

为什么说UDP存在数据边界?

因为:

1.与TCP不同,UDP的通信过程中,I/O函数的调用次数必须保持一致,即客户端sendto了几次,服务器端也要recvfrom几次。

2.同时也因为UDP每次传输的数据包又称为UDP数据报,数据报也是数据包的一种,不同的是,UDP数据报本身可以成为1个完整的数据,而TCP的一个完整的数据可以由多个数据包组成。

4. UDP的I/O函数

4.1 sendto函数

cpp 复制代码
#include<sys/socket.h>
ssize_t sendto(
int sock,                     //用于传输数据的UDP套接字文件描述符
void *buff,                   //保存待传输数据的缓冲地址值
size_t nbytes,                //待传输的数据长度,以字节为单位
int flags,                    //可选项参数,没有就设置为0
struct sockaddr* to,          //存有目标地址信息的sockaddr结构体变量的地址值
socklen_t addrlen             //传递给参数to的地址值结构体变量长度
);
成功返回传输的字节数,失败返回-1

UDP的套接字不会保持连接状态,因此每次传输数据都要添加目标地址信息。

4.2 recvfrom函数

cpp 复制代码
#include<sys/socket.h>
ssize_t recvfrom(
int sock,                //用于接收数据的UDP套接字文件描述符
void* buff,              //保存接收数据的缓冲地址值
size_t nbytes,           //可接受的最大字节数,无法超过buff的大小
int flags,               //可选项参数,没有则传0
struct sockaddr* from,   //存有发送端地址信息的sockaddr结构体变量的地址值
socklen_t *addrlen       //保存参数from的结构体变量长度的地址值
);

4. 已连接(connected)UDP套接字和未连接(unconnected)UDP套接字

已连接UDP套接字:执行了connect函数或bind函数,套接字绑定了某主机IP和端口号

未连接UDP套接字:未执行connect函数或bind函数,套接字在每次执行sendto函数时,再绑定某主机IP和端口号。

UDP中通过sendto函数传输数据可分为三个阶段:

  1. 第一阶段:向UDP套接字注册目标IP和端口号
  2. 第二阶段:传输数据
  3. 第三阶段:删除UDP套接字中注册的目标信息地址

所以,未连接UDP套接字,可以重复利用同一个UDP套接字,向不同主机传输数据。但如果你每次都是向同一个主机传输多次,那么上述阶段会重复多次,这样会大大的消耗程序性能,因为sendto函数的第一阶段和第三阶段占整个通信过程的1/3,所以,这种情况下,你可以使用已连接套接字,在sendto函数前就先调用connect函数或bind函数,绑定IP和端口号,这样sendto函数就会节省第一阶段和第二阶段的时间,提高程序效率。

5. UDP的通信流程

5.1 服务器端通信流程

第一步:使用socket函数创建套接字

第二步:使用bind函数绑定IP地址和端口号(可以省略这一步,但如果是多次要与同一个主机通信,那么增加这一步可以增加性能)

第三步:使用sendto(或write)发送信息或recvfrom(或recv)接收信息(能使用send和recv的前提是已连接UDP套接字)

第四步:关闭套接字

和TCP不一样,UDP无需执行listen,accept函数,可以不执行bind函数。

5.2 客户端通信流程

第一步:使用socket函数创建套接字

第二步:使用connect函数连接IP地址和端口号(可以省略这一步,但如果是多次要与同一个主机通信,那么增加这一步可以增加性能)

第三步:使用sendto(或write)发送信息或recvfrom(或recv)接收信息(能使用send和recv的前提是已连接UDP套接字)

第四步:关闭套接字

和TCP不一样,UDP可以不执行connect函数,连接服务器端。

相关推荐
hhhjhl7 小时前
Protobuf.js 跨端三方库仓颉适配全流程
javascript·网络·udp
ITxiaobing20238 小时前
中国公司海外广告投放的 IP 地址库选型:从“查归属”到“验真实”的工程视角
网络·网络协议·tcp/ip
KKKlucifer8 小时前
运营商非结构化文档安全管控体系建设实践
大数据·网络·安全
xiaoye-duck8 小时前
《C++ 工具库实战》gflags 命令行参数解析库详解
c++·第三方库
狂奔的sherry9 小时前
C++ 宏生成访问函数的代价:访问权限、调试和类型检查
c++·宏·编译·预处理器·类型检查
网络小江10 小时前
组网第35课:静态路由——下一跳、出接口、默认路由、浮动静态与黑洞路由
服务器·网络·默认路由·黑洞路由·浮动静态路由
划破黑暗的第一缕曙光10 小时前
[C++]:5.STL:string(2)
java·c++·redis
acrel711 小时前
医院用电隐患治理与节能降耗及智慧能源平台应用
网络·数据库
Escalating_xu11 小时前
【Linux 网络编程】应用层协议 HTTP(下):Header、连接管理与 C++ HTTP 服务器
linux·服务器·网络
明天也要努力学习13 小时前
TCP 协议的相关特性
网络·网络协议·tcp/ip