UDP无连接 不可靠 数据报服务
无连接:收发数据只用指定双发的ip端口,存写数据的来源 ip端口
不可靠:尽可能传输
UDP报文的特点

UDP服务器端代码:
cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
// 1. 创建UDP套接字:SOCK_DGRAM代表UDP协议
int sockfd = socket(AF_INET,SOCK_DGRAM,0);
if ( sockfd == -1 )
{
exit(1);
}
// 2. 绑定本地IP和端口(UDP也需要绑定,让客户端知道往哪个端口发消息)
struct sockaddr_in saddr;
memset(&saddr,0,sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(6000);
saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
int res = bind(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));
if( res == -1 )
{
printf("bind err\n");
exit(1);
}
struct sockaddr_in caddr; // 用于存储客户端的地址信息
while(1)
{
int len = sizeof(caddr);
char buff[128] = {0};
// 3. 接收客户端消息:recvfrom是UDP专用的接收函数(阻塞等待)
// 会同时获取客户端的地址信息(存在caddr中)
recvfrom(sockfd,buff,127,0,(struct sockaddr*)&caddr,&len);
printf("buff=%s\n",buff);
// 4. 回复客户端消息:sendto通过caddr指定回复的目标客户端
sendto(sockfd,"ok",2,0,(struct sockaddr*)&caddr,sizeof(caddr));
}
close(sockfd);
}
-
套接字类型
- UDP 使用
SOCK_DGRAM(数据报),TCP 使用SOCK_STREAM(字节流); - UDP 是 "无连接" 协议,不需要
listen()/accept()/connect(),直接通过recvfrom/sendto收发消息。
- UDP 使用
-
收发函数
- UDP 用
recvfrom/sendto:必须指定目标客户端的地址(因为无连接,每次收发都要明确对方地址); - TCP 用
recv/send:连接建立后,直接通过已连接的套接字通信(不需要每次指定地址)。
- UDP 用
-
连接特性
- UDP 无连接:客户端不需要 "连接",直接往服务器端口发消息即可;
- 服务器通过
recvfrom获取客户端地址,再用sendto回复。
代码运行逻辑
- 服务器启动后,绑定
127.0.0.1:6000端口; - 进入循环,阻塞在
recvfrom等待客户端消息; - 客户端向
127.0.0.1:6000发送消息后,服务器通过recvfrom接收消息和客户端地址; - 服务器打印消息,并通过
sendto向该客户端回复 "ok"; - 循环等待下一条消息。
UDP客户端代码
cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
// 1. 创建UDP套接字(SOCK_DGRAM表示UDP协议)
int sockfd = socket(AF_INET,SOCK_DGRAM,0);//udp
if ( sockfd == -1 )
{
exit(1);
}
// 2. 配置服务器的IP和端口(指定消息要发送到的目标)
struct sockaddr_in saddr;//ser ip port
memset(&saddr,0,sizeof(saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(6000);
saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
while( 1 )
{
printf("input:\n");
char buff[128] = {0};
fgets(buff,128,stdin); // 从键盘输入要发送的内容
// 输入"end"则退出循环
if ( strncmp(buff,"end",3) == 0 )
{
break;
}
// 3. 向服务器发送消息(sendto指定目标服务器地址)
sendto(sockfd,buff,strlen(buff)-1,0,(struct sockaddr*)&saddr,sizeof(saddr));
memset(buff,0,128); // 清空缓冲区
int len = sizeof(saddr);
// 4. 接收服务器的回复(recvfrom获取服务器的回复)
recvfrom(sockfd,buff,127,0,(struct sockaddr*)&saddr,&len);
printf("buff=%s\n",buff);
}
close(sockfd); // 关闭套接字
exit(0);
}
-
无连接通信 UDP 客户端不需要像 TCP 那样调用
connect()建立连接,直接通过sendto指定服务器地址即可发送消息,是 "无状态" 的通信方式。 -
收发函数的使用
- 用
sendto发送消息:必须传入服务器的地址结构体(明确消息发往哪里); - 用
recvfrom接收回复:会同时获取服务器的地址(实际场景中可用于区分不同服务器)。
- 用
-
循环交互逻辑 客户端通过
while(1)实现 "多次输入→发送→接收回复" 的循环,输入 "end" 可退出,符合实际场景中多次通信的需求。
与 UDP 服务器的通信流程
- 客户端创建 UDP 套接字,配置服务器的 IP(127.0.0.1)和端口(6000);
- 客户端输入消息,通过
sendto发送到服务器; - 服务器通过
recvfrom接收消息,处理后用sendto回复 "ok"; - 客户端通过
recvfrom接收回复并打印; - 重复上述步骤,直到输入 "end" 退出。
测试

UDP 客户端与服务器的通信测试结果,体现了 UDP 无连接通信的核心特性,可从以下几点分析:
1. 测试流程与现象
- 服务器(左侧终端) :启动
./udpser后,依次接收到客户端发送的hello、abc、1234、777,并打印这些消息; - 客户端(右侧两个终端) :启动
./udpcli后,输入消息(如hello),发送给服务器后收到回复ok,实现 "输入→发送→接收回复" 的循环。
2. 体现的 UDP 特性
- 无连接、多客户端支持 :右侧启动了两个客户端 ,都能向同一服务器发送消息,服务器无需 "建立连接" 即可接收所有客户端的消息(UDP 无连接特性,不区分客户端,只根据
recvfrom获取的地址回复); - 轻量交互 :客户端无需像 TCP 那样先
connect,直接发送消息,流程更简洁; - 数据报通信 :每个
sendto对应一个独立的数据报,服务器按收到的顺序打印(UDP 不保证顺序,但本测试中网络稳定,顺序一致)。
无连接特性

该现象是 UDP 无连接通信 的典型特征:关闭 UDP 服务器后,客户端调用sendto()发送数据依然成功、无报错,仅卡在recvfrom()阻塞等待回复 → 完美证明 UDP 无连接本质。
UDP 面试核心要点
1. 基本定义
- 是无连接、不可靠、基于数据报的传输层协议,全称为 User Datagram Protocol(用户数据报协议)。
2. 核心特性
| 特性 | 说明 |
|---|---|
| 无连接 | 无需connect()建立连接,客户端 / 服务器无专属链路,互相不感知对方状态。 |
| 不可靠 | 无确认、无重传、无差错恢复,数据可能丢包、乱序,不保证送达。 |
| 基于数据报 | 每个sendto()对应一个独立数据报,大小受限(通常不超过 65535 字节)。 |
| 轻量高效 | 无连接开销、头部仅 8 字节(TCP 头部 20~60 字节),传输速度快。 |
3. 关键函数(代码层面)
- 套接字创建:
socket(AF_INET, SOCK_DGRAM, 0)(SOCK_DGRAM表示 UDP)。 - 发送:
sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen)→ 需指定目标地址,不校验对端状态,发送即返回成功。 - 接收:
recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen)→ 阻塞等待,可获取发送方地址。
4. 与 TCP 的核心区别
| 维度 | TCP(有连接) | UDP(无连接) |
|---|---|---|
| 连接关系 | 需建立专属链路,感知对端状态 | 无链路、无绑定,不感知对端状态 |
| 可靠性 | 可靠(确认、重传、有序) | 不可靠(无确认、可能丢包) |
| 效率 | 低(连接 / 头部开销大) | 高(轻量、无额外开销) |
| 适用场景 | 文件传输、登录等(需可靠) | 直播、语音、DNS 查询等(需实时) |
5. 典型场景
适用于实时性优先、可容忍少量丢包的场景:直播 / 视频流、语音通话、DNS 查询、物联网传感器数据传输等。
6. 高频面试题
- 问:UDP 为什么无连接?答:客户端与服务器无专属通信链路,无需建立连接即可收发数据,互相不感知对方状态。
- 问:UDP 发送数据一定能到吗?答:不一定,UDP 无确认 / 重传机制,数据可能在网络中丢失,仅保证 "发出去"。
- 问:UDP 头部有哪些字段?答:源端口、目的端口、长度、校验和(共 8 字节)。