news 2026/6/22 20:08:47

网络编程:UDP Socket

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
网络编程:UDP Socket

1 核心概念

1.1 UDP (User Datagram Protocol)
  • 定义:用户数据报协议。是一种无连接的、不可靠的、基于数据报的传输层协议。
  • 本质:只负责把数据包扔出去,不保证对方收到,也不保证顺序。类似于“寄信”或“发短信”。
  • 特点
    • 无连接 (Connectionless):通信前不需要建立连接(无三次握手),结束时不需要断开(无四次挥手)。
    • 不可靠 (Unreliable):不提供重传、排序、流量控制机制。数据可能丢失、重复或乱序。
    • 面向数据报 (Datagram):保留数据边界。发送方发 100 字节,接收方就得一次收 100 字节(不会像 TCP 那样出现粘包)。
    • 高效:头部开销小(仅 8 字节),实时性高,适合视频会议、直播、广播等场景。
1.2 关键区别 (TCP vs UDP)
特性TCP (打电话)UDP (发短信)
连接性面向连接 (三次握手)无连接
可靠性可靠 (重传、排序、校验)不可靠 (尽力而为)
传输模式字节流 (Stream)数据报 (Datagram)
Socket 类型SOCK_STREAMSOCK_DGRAM
核心 APIread/writerecvfrom/sendto
应用场景网页(HTTP)、文件传输(FTP)视频流、DNS、广播

2 关键数据结构

需包含头文件:#include <netinet/in.h>

UDP 使用与 TCP 完全相同的地址结构体,没有区别。

IPv4 专用地址结构体

structsockaddr_in{shortintsin_family;// 地址族 (必须设为 AF_INET)unsignedshortintsin_port;// 端口号 (网络字节序, 使用 htons)structin_addrsin_addr;// IP 地址结构体unsignedcharsin_zero[8];// 填充字节 (置0)};structin_addr{unsignedlongs_addr;// 32位 IP 地址 (网络字节序)};

3 核心 API

需包含头文件:#include <sys/socket.h>

3.1 创建套接字
intsocket(intdomain,inttype,intprotocol);
  • type: 使用SOCK_DGRAM(数据报套接字)。
3.2 绑定地址 (bind)
intbind(intsockfd,conststructsockaddr*addr,socklen_taddrlen);
  • 接收端 (Server)必须绑定。类似于在门口挂个信箱,否则不知道收谁的信。
  • 发送端 (Client)通常不需要绑定。系统会自动分配一个临时端口发送数据。
3.3 数据接收 (recvfrom)

UDP 没有连接,不知道数据从哪来,所以接收时必须同时拿“信的数据”和“发信人的地址”。

ssize_trecvfrom(intsockfd,void*buf,size_tlen,intflags,structsockaddr*src_addr,socklen_t*addrlen);
  • 功能:接收数据,并获取发送者的地址信息。
  • 参数
    • src_addr:(传出参数) 用来存储发送方的 IP 和端口信息。
    • addrlen:(传入传出参数)src_addr的长度。
  • 返回值:成功返回接收到的字节数,失败返回 -1。
  • 注意:如果不关心是谁发的,后两个参数可填NULL
3.4 数据发送 (sendto)

UDP 没有连接,发送时必须每次都指定“发给谁”。

ssize_tsendto(intsockfd,constvoid*buf,size_tlen,intflags,conststructsockaddr*dest_addr,socklen_taddrlen);
  • 功能:向指定的目标地址发送数据。
  • 参数
    • dest_addr:(传入参数)接收方的目标 IP 和端口结构体。
    • addrlendest_addr的长度。
  • 返回值:成功返回发送的字节数,失败返回 -1。
3.5 UDP 中通常不用
  • listen():UDP 不需要监听,因为没有连接请求。
  • accept():UDP 不需要接受连接。
  • connect():UDP 可以调用,但含义不同(变为“已连接 UDP”),一般很少用。

4 标准 UDP 编程模型

阶段接收端 (Receiver/Server)发送端 (Sender/Client)
1. 准备socket(..., SOCK_DGRAM, ...)socket(..., SOCK_DGRAM, ...)
2. 地址填充sockaddr_in(本机 IP+端口)填充sockaddr_in(目标 IP+端口)
3. 绑定bind()必须执行(通常省略,系统自动分配)
4. 通信recvfrom()(阻塞等待数据,获取对方地址)sendto()(直接发送,需指定目标地址)
5. 回复sendto()(利用 recvfrom 得到的地址回复)recvfrom()(如果需要等待回复)
6. 结束close()close()

5. UDP Echo 实验代码

5.1 接收端代码 (Server)

负责接收数据,打印发送者 IP,并原样回传。

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<arpa/inet.h>#include<sys/socket.h>#definePORT8888#defineBUFFER_SIZE1024intmain(){intsockfd;structsockaddr_inserv_addr,client_addr;charbuffer[BUFFER_SIZE];socklen_taddr_len=sizeof(client_addr);// 1. 创建 UDP Socketif((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0){perror("socket");exit(1);}// 2. 绑定地址 (Server 必须 Bind)memset(&serv_addr,0,sizeof(serv_addr));serv_addr.sin_family=AF_INET;serv_addr.sin_addr.s_addr=INADDR_ANY;// 监听所有网卡serv_addr.sin_port=htons(PORT);if(bind(sockfd,(structsockaddr*)&serv_addr,sizeof(serv_addr))<0){perror("bind");exit(1);}printf("[UDP Server] Listening on port %d...\n",PORT);while(1){memset(buffer,0,BUFFER_SIZE);// 3. 接收数据 (同时获取对方地址)intlen=recvfrom(sockfd,buffer,BUFFER_SIZE,0,(structsockaddr*)&client_addr,&addr_len);if(len>0){buffer[len]='\0';// 添加字符串结束符printf("Received from %s: %s\n",inet_ntoa(client_addr.sin_addr),buffer);// 4. 回复数据 (发回给 sender)sendto(sockfd,buffer,len,0,(structsockaddr*)&client_addr,addr_len);}}close(sockfd);return0;}
6.2 发送端代码 (Client)

负责发送数据到指定 IP,并等待回复。

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<arpa/inet.h>#include<sys/socket.h>#defineSERVER_PORT8888#defineSERVER_IP"192.168.7.2"// 板子IPintmain(intargc,char*argv[]){intsockfd;structsockaddr_inserv_addr;charbuffer[1024];// 1. 创建 UDP Socketif((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0){perror("socket");exit(1);}// 2. 配置目标地址memset(&serv_addr,0,sizeof(serv_addr));serv_addr.sin_family=AF_INET;serv_addr.sin_port=htons(SERVER_PORT);inet_pton(AF_INET,(argc>1?argv[1]:SERVER_IP),&serv_addr.sin_addr);while(1){printf("Input > ");fgets(buffer,sizeof(buffer),stdin);// 3. 发送数据 (指定发给 serv_addr)sendto(sockfd,buffer,strlen(buffer),0,(structsockaddr*)&serv_addr,sizeof(serv_addr));// 4. 接收回复memset(buffer,0,sizeof(buffer));intlen=recvfrom(sockfd,buffer,sizeof(buffer),0,NULL,NULL);// 不关心是谁回的,填NULLif(len>0){buffer[len]='\0';printf("Echo: %s\n",buffer);}}close(sockfd);return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/23 14:45:26

DAIR-V2X车路协同实战手册:从数据到决策的全链路解密

DAIR-V2X车路协同实战手册&#xff1a;从数据到决策的全链路解密 【免费下载链接】DAIR-V2X 项目地址: https://gitcode.com/gh_mirrors/da/DAIR-V2X 技术痛点&#xff1a;为什么单车智能不够用&#xff1f; 在真实的城市道路环境中&#xff0c;单车智能面临着三大技术…

作者头像 李华
网站建设 2026/6/23 18:10:18

EmotiVoice语音温度调节概念引入,冷暖随心

EmotiVoice&#xff1a;让语音拥有情感温度 在智能音箱轻声回应“好的&#xff0c;马上为您播放音乐”的那一刻&#xff0c;你是否曾希望它的语气不是千篇一律的平静&#xff0c;而是能因你的喜悦而欢快、因你的疲惫而温柔&#xff1f;当虚拟助手读出天气预报时&#xff0c;如果…

作者头像 李华
网站建设 2026/6/23 7:34:25

Rainmeter官网中文版下载和安装教程(附安装包,超级详细)

Rainmeter&#xff08;中文名雨滴桌面&#xff09;是一款专为 Windows 系统设计的桌面定制工具。Rainmeter 的作用是让原本单调的电脑桌面变得既美观又实用。简单来说&#xff0c;它就像给桌面装上了一个可自由搭配的 “功能面板”&#xff0c;通过各种“皮肤”组件&#xff0c…

作者头像 李华
网站建设 2026/6/23 18:11:27

EmotiVoice语音合成抗噪能力测试:嘈杂环境中仍清晰可辨

EmotiVoice语音合成抗噪能力测试&#xff1a;嘈杂环境中仍清晰可辨 在车载导航播报被引擎轰鸣淹没、智能音箱在厨房嘈杂中语焉不详的今天&#xff0c;我们对“能听清”的期待早已超越了简单的语音输出——真正可用的TTS系统必须能在真实世界的噪声洪流中稳稳站住脚。而EmotiVo…

作者头像 李华
网站建设 2026/6/23 18:09:34

邦邦汽服携手吉利循环产业中心解锁汽车后市场绿色循环新路径

2025年12月10日&#xff0c;邦邦汽车销售服务&#xff08;北京&#xff09;有限公司与吉利循环产业中心战略合作签约仪式在宁国经济技术开发区圆满举行。宁国市政府及经开区有关领导、人保金服与人保财险安徽分公司有关领导、双方业务负责人及团队代表共同出席仪式。与会嘉宾先…

作者头像 李华
网站建设 2026/6/23 18:55:56

浅谈:算法中的斐波那契数(四)

方法三&#xff1a;记忆化自顶向下的方法我们先计算存储子问题的答案&#xff0c;然后利用子问题的答案计算当前斐波那契数的答案。我们将递归计算&#xff0c;但是通过记忆化不重复计算已计算的值。算法&#xff1a;如果 N < 1&#xff0c;则返回 N。调用和返回 memoize(N)…

作者头像 李华