UDP编程

UDP(User Datagram Protocol)是一种无连接的传输层协议,位于OSI模型的第四层。与TCP不同,UDP不提供可靠性保证、流量控制或拥塞控制机制,但具有低延迟和高效率的特点。

UDP的主要特性

无连接性

UDP在通信前无需建立连接,直接发送数据报。这减少了握手和断连的开销,但无法保证数据包的顺序或完整性。

不可靠传输

UDP不提供确认、重传或错误恢复机制。若数据包丢失或损坏,协议本身不会主动处理,需由应用层解决。

低开销

UDP头部仅8字节(包含源端口、目标端口、长度和校验和),远小于TCP的20字节头部,减少了传输负担。

支持广播和多播

UDP能够向多个目标同时发送数据包(广播或多播),适用于实时音视频、在线游戏等场景。

UDP的典型应用场景

  • 实时多媒体传输:如VoIP(语音通话)、视频会议(如Zoom部分使用UDP)。
  • 在线游戏:对延迟敏感的场景优先选择UDP,例如FPS游戏。
  • DNS查询:DNS协议默认使用UDP,快速解析域名。
  • IoT设备通信:传感器数据上报等轻量级通信。

UDP与TCP的对比

特性 UDP TCP
连接方式 无连接 面向连接
可靠性 不可靠 可靠(确认、重传)
传输效率 高(低开销) 较低(头部大)
数据顺序 不保证 保证按序到达
适用场景 实时应用、广播 文件传输、网页浏览

UDP的编程函数

在UDP中我们用到的函数如下

服务器端:

UDP编程常用函数

socket()

创建套接字,指定协议族(如AF_INET)和套接字类型(SOCK_DGRAM)。

复制代码
int socket(int domain, int type, int protocol);
bind()

将套接字绑定到本地IP地址和端口,通常用于服务器端。

复制代码
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sendto()

发送数据到指定的目标地址,适用于无连接的UDP通信。

cpp 复制代码
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
               const struct sockaddr *dest_addr, socklen_t addrlen);
recvfrom()

接收数据并获取发送方的地址信息,常用于服务器或客户端接收响应。

cpp 复制代码
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                 struct sockaddr *src_addr, socklen_t *addrlen);
close()

关闭套接字释放资源。

cpp 复制代码
int close(int sockfd);

UDP客户端

socket()

sendto()

recevfrom()

close()

使用socket()创建套接字,使用UDP协议时,选择的SOCK_DGRAM,使用sendto()发送资源,由于UDP时无连接的,每次都要发送数据都需要指定对端的地址,recbform()接收数据,每次都需要传给该方法的一个地址结构存放发送端的地址,recvform()可以接收所有客户端发送给当前应用程序的数据,并不能接收一个客户端的数据.

UDP服务器代码

cpp 复制代码
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include<arpa/inet.h>
#include<pthread.h>
int main(){
int sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(-1==sockfd)
{
exit(1);
}
struct sockaddr_in saddr;
memset(&saddr,0,sizeof(saddr));
saddr.sin_family=AF_INET;
saddr.sin_port=htons(9999);
saddr.sin_addr.s_addr=inet_addr("127.0.0.1");
int n=bind(sockfd,(struct sockaddr *)&saddr,sizeof(saddr));
if(-1==n){
    printf("bind arror");
    exit(1);
}
while(1){
char buf[128]={0};
 int len=sizeof(saddr);
int n=recvfrom(sockfd,buf,127,
0,(struct sockarr *)&saddr,&len);
sendto(sockfd,buf,sizeof(buf)-1,0,(struct sockarr*)&saddr,sizeof(saddr));
if(n<0){
    break;
}
printf("%s",buf);
sendto(sockfd,"YES",3,0,(struct sockaddr *)&saddr,len);

}
close(sockfd);
}

UDP客户端代码

cpp 复制代码
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<string.h>
#include<arpa/inet.h>
int main(){
int sockfd=socket(AF_INET,SOCK_DGRAM,0);
if(-1==sockfd)
{
exit(1);
}
struct sockaddr_in saddr;
memset(&saddr,0,sizeof(saddr));
saddr.sin_family=AF_INET;
saddr.sin_port=htons(9999);
saddr.sin_addr.s_addr=inet_addr("127.0.0.1");
char buf[128]={0};
fgets(&buf,127,stdin);
int n=sendto(sockfd,buf,127,0,
    (struct sockaddr *)&saddr,sizeof(saddr));
 recvfrom(sockfd,buf , 127, 0,(struct sockaddr *)&saddr, sizeof(saddr));

        printf("buff = %s\n", buf); 
        close(sockfd);     

}
相关推荐
咖丨喱11 分钟前
IP校验和算法解析与实现
网络·tcp/ip·算法
那就回到过去40 分钟前
交换机特性
网络·hcip·ensp·交换机
lpruoyu1 小时前
【Docker进阶-05】Docker网络
网络·docker·容器
小李独爱秋2 小时前
计算机网络经典问题透视:蜂窝网络切换如何“扼杀”你的TCP连接?
网络·网络协议·tcp/ip·计算机网络·php·信息与通信
路由侠内网穿透.2 小时前
本地部署代码托管解决方案 Gitea 并实现外部访问( Windows 版本)
运维·服务器·网络协议·gitea
犀思云2 小时前
企业总部网络全球化扩张:利用FusionWAN NaaS 破解“网络成本瓶颈”
网络·人工智能·机器人·智能仓储·专线
xixixi777773 小时前
互联网和数据分析中的核心指标 DAU (日活跃用户数)
大数据·网络·数据库·数据·dau·mau·留存率
焦点链创研究所3 小时前
去中心化实体基础设施网络的崛起:比较分析
网络·去中心化·区块链
迎仔4 小时前
00-网络技术体系总览:从信息孤岛到数字世界的高速公路
网络
leaguecn4 小时前
ArcGIS授权管理器断网后自动停止
网络·arcgis·授权