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);     

}
相关推荐
其实防守也摸鱼9 小时前
补天SRC新手入门指南:从0到1的漏洞挖掘之路
网络·python·学习·安全·web安全·数据挖掘·挖洞
运维行者_10 小时前
如何查看每个IP的带宽使用情况?NetFlow 技术实战指南
开发语言·网络·分布式·后端·架构·带宽
振浩微433射频芯片10 小时前
工业遥控器总在关键时刻“掉链子”?——433MHz芯片方案如何破局
网络·单片机·嵌入式硬件·物联网·工业遥控
AGCSDNl11 小时前
线上起名网站深度测评
网络
2501_9160074711 小时前
深入理解HTTPS对称与非对称加密机制及Charles抓包实践
网络协议·http·ios·小程序·https·uni-app·iphone
2501_9160088911 小时前
HTTPS 抓包遇到证书绑定怎么办,使用 TraceEagle 解除 App 证书校验
网络协议·计算机网络·http·网络安全·ios·adb·https
weixin_7275356211 小时前
OSI 七层模型概览
网络
不是光头 强12 小时前
接口性能优化报告
网络协议·性能优化·rpc
Eloudy12 小时前
Chapter02 - 互连网络原理与实践:一个简单的互连网络
网络
数智化管理手记12 小时前
应收应付资金占用过高怎么办?应收应付搭配账龄分析怎么做
大数据·网络·数据库·人工智能·数据挖掘